Есть ли способ в bash для глобальных файлов, которые не заканчиваются определенным суффиксом?
например, я делаю это:
mv $ INCDIR/HDR_10_ * $ BACKUPDIR
Но я не хочу перемещать HDR_10_ *, который заканчивается на .gz
Это будет работать для перемещения файла:
mv $( echo $INCDIR/HDR_10_* | grep -v '\.gz$') $BACKUPDIR
Вы также просили 'глобировать файлы, которые не заканчиваются определенным суффиксом?У Bash есть опция оболочки (shopt) extglob, которая позволяет использовать расширенный синтаксис глобализации. !(...glob...)
соответствует всему, кроме шаблона glob.
shopt -s extglob
cd $INCDIR
mv !(*.gz) $BACKUPDIR
будет работать, только если $ INCDIR содержит только файлы с именем HDR_10_ *, в частности, он будет соответствовать любому файлу или каталогу в $ INCDIR, который не соответствует * .gz. Технически вы просите глобус, который соответствует одному шаблону, но не другому, который, я думаю, не существует как простая единая сущность.
Под кш !(*.gz)
соответствует всем файлам в текущем каталоге, кроме файлов, которые соответствуют *.gz
. Тот же шаблон работает в bash после shopt -s extglob
и в zsh после setopt ksh_glob
. Ни ksh, ни bash не могут пересечь положительное и отрицательное совпадения. В zsh после setopt extended_glob
вы можете написать $INCDIR/HDR_10_*~$INCDIR/*.gz
.
Одним из решений в любой оболочке в стиле Борна (ash, bash, ksh, zsh, ...) является перебор файлов и проверка каждого совпадения.
for x in "$INCDIR"/HDR_10_*; do
case "$x" in
*.gz) :;;
*) mv -- "$x" "$BACKUPDIR";;
esac
done
Другое решение - использовать find
. Следующая команда также перемещает файлы в подкаталогах.
find "$INCDIR" -type f -name 'HDR_10_*' \! -name '*.gz' -exec mv {} "$BACKUPDIR" \;
Если у вас есть GNU find (например, в Linux), вы можете добавить -maxdepth 1
после "$INCDIR"
чтобы перемещать файлы только непосредственно в $INCDIR
.
Обратите внимание, что вы всегда должны использовать двойные кавычки вокруг подстановок переменных (например, "$INCDIR"
, а не $INCDIR
), если у вас нет веских причин для их исключения. В противном случае у вас возникнут проблемы, если у вас есть файлы, имя которых содержит специальные символы, такие как пробел или \[?*
Если вы используете find
, grep
и xargs
, вы можете сделать это довольно легко.
Я уверен, что есть лучшие конструкции, но это то, что приходит на ум сразу:
# find <here>| <pattern> | <notpattern>| <what to do>
find $INCDIR | grep HDR_10_ | grep -v .gz | xargs mv $BACKUPDIR
В комментариях было отмечено исправление, что вышеупомянутый быстрый удар не будет работать, потому что mv
не получает свои аргументы в правильном порядке от xargs
:
find $INCDIR -name 'HDR_10_*' ! -name '*.gz' -exec mv {} $BACKUPDIR \