4

Есть ли способ в bash для глобальных файлов, которые не заканчиваются определенным суффиксом?

например, я делаю это:

mv $ INCDIR/HDR_10_ * $ BACKUPDIR

Но я не хочу перемещать HDR_10_ *, который заканчивается на .gz

3 ответа3

4

Это будет работать для перемещения файла:

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. Технически вы просите глобус, который соответствует одному шаблону, но не другому, который, я думаю, не существует как простая единая сущность.

1

Под кш !(*.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), если у вас нет веских причин для их исключения. В противном случае у вас возникнут проблемы, если у вас есть файлы, имя которых содержит специальные символы, такие как пробел или \[?*

1

Если вы используете 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 \

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .