Похоже, что вы хотите избежать поиска файлов в каталогах *cache*
больше, чем найти файлы с *pillar*
, а не *cache*
в имени. Тогда просто скажите find
не спускаться в каталоги *cache*
:
find . -iname '*cache*' -prune -o -iname '*pillar*' -print
Или с помощью zsh -o extendedglob
:
ls -ld -- (#i)(^*cache*/)#*pillar*
(не совсем эквивалентно, так как это сообщит о foo/pillar-cache
файле)
Или (менее эффективно, так как спускается по всему дереву, как в @apaul's solution):
ls -ld -- (#i)**/*pillar*~*cache*
Подробности о zsh
специфических глобусах:
(#i)
: включение нечувствительного к регистру соответствия^
: оператор отрицания глобуса(. ...)
: группировка (как @(...)
в ksh
). #
: ноль или более из
(как *
в regexps). ~
: оператор and-not (соответствует всему пути)**/
: 0 или более уровней каталога (сокращение для (*/)#
). Добавьте классификатор (D)
glob, если вы хотите спуститься в скрытые каталоги и найти скрытые файлы, как в решении find
.
Ну, это действительно отвечает на мой вопрос конкретно, в этом комментарии Ре :Кусалананды, если он найдет более 2 файлов, он все испортит и удалит неправильные файлы. Этот скрипт предназначен для того, что мне нужно, но может быть адаптирован для других целей.
#!/bin/bash
#Create Log with Single Entry for Each Duplicate Without File Extension
duplog='dupes.log'
ls * | awk '!/.srt/' | sed 's/.\{4\}$//' | sort | uniq -d > "$duplog"
#Testing!
cat "$duplog"
#List Each Iteration of File in log starting with Largest File
log='tmp.log'
while read p; do
#More Testing!
du -k "$p".*
ls -1S "$p".* >> "$log"
done < $duplog
#Testing!
cat "$log"
#Remove Large File Entry via Sed
#Note: This relies on only two variations being found or it will delete wrong lines in file
sed -i '1~2d' "$log"
#Testing!
cat "$log"
#Delete Smaller File
while read p; do
echo "Deleting $p"
rm "$p"
done <"$log"
#Delete Log
rm "$log"
Выход:
root@fs:/Movies# du -k tk.m*
4 tk.mkv
0 tk.mp4
root@fs:/Movies#./test.sh
tk
4 tk.mkv
0 tk.mp4
tk.mkv
tk.mp4
tk.mp4
Deleting tk.mp4
root@fs:/Movies#
PS :Я уверен, что это "хакерство", но это работает для того, что мне нужно, и это еще один шаг в процессе обучения:)
Предложение:
#!/bin/sh
# Look at filenames in current directory and generate list with filename
# suffixes removed (a filename suffix is anything after the last dot in
# the file name). We assume filenames that does not contain newlines.
# Only unique prefixes will be generated.
for name in./*; do
[ ! -f "$name" ] && continue # skip non-regular files
printf '%s\n' "${name%.*}"
done | sort -u |
while IFS= read -r prefix; do
# Set the positional parameters to the names matching a particular prefix.
set -- "$prefix"*
if [ "$#" -ne 2 ]; then
printf 'Not exactly two files having prefix "%s"\n' "$prefix" >&2
continue
fi
# Check file sizes and remove smallest.
if [ "$( stat -c '%s' "$1" )" -lt "$( stat -c '%s' "$2" )" ]; then
# First file is smaller
printf 'Would remove "%s"\n' "$1"
echo rm "$1"
else
# Second file is smaller, or same size
printf 'Would remove "%s"\n' "$2"
echo rm "$2"
fi
done
Это предполагает GNU stat
.