Скажем, я хочу скопировать содержимое каталога, исключая файлы и папки, имена которых содержат слово «Музыка».
cp [exclude-matches] *Music* /target_directory
Что должно пойти вместо [exclude-match] для достижения этой цели?
bash
shell
pattern-matching
glob
user4812
источник
источник
ls /dir/*/!(base*)
f
, кромеfoo
?Опция
extglob
оболочки дает вам более мощное сопоставление с образцом в командной строке.Вы включаете его с помощью
shopt -s extglob
, а выключаете его с помощьюshopt -u extglob
.В вашем примере вы бы изначально сделали:
Полный доступен внутр закончился GLOB операторы Бинг являются (выдержка из
man bash
):Так, например, если вы хотите , чтобы получить список всех файлов в текущем каталоге, которые не являются
.c
или.h
файлы, вы должны сделать следующее :Конечно, нормальное сглаживание оболочки работает, поэтому последний пример также можно записать так:
источник
.c
или.h
является каталогом.D
, но не содержимое подкаталогов, которые могут содержаться в каталогеD
.Не в bash (что я знаю), но:
Я знаю, что это не совсем то, что вы искали, но это решит ваш пример.
источник
Если вы хотите избежать затрат на использование команды exec, я думаю, вы можете добиться большего успеха с помощью xargs. Я думаю, что следующее является более эффективной альтернативой
источник
В bash альтернативой
shopt -s extglob
являетсяGLOBIGNORE
переменная . Это не совсем лучше, но мне легче запомнить.Пример, который может быть тем, что хотел оригинальный плакат:
Когда это
unset GLOBIGNORE
будет сделано, чтобы иметь возможностьrm *techno*
в исходном каталоге.источник
Вы также можете использовать довольно простой
for
цикл:источник
-maxdepth 1
для нерекурсивных?find
обратных галочек будет нарушать неприятные способы, если он найдет какие-либо нетривиальные имена файлов.Мое личное предпочтение - использовать команду grep и while. Это позволяет писать мощные, но читаемые сценарии, гарантирующие, что вы в конечном итоге будете делать именно то, что вам нужно. Кроме того, с помощью команды echo вы можете выполнить пробный прогон перед выполнением фактической операции. Например:
распечатает файлы, которые вы в конечном итоге скопировать. Если список правильный, следующий шаг - просто заменить команду echo командой copy следующим образом:
источник
bash
вы можете использоватьwhile IFS='' read -r filename
, но тогда новые строки по - прежнему является проблемой. В общем, лучше не использоватьls
для перечисления файлов; инструменты, какfind
гораздо лучше подходят.for file in *; do case ${file} in (*Music*) ;; (*) cp "${file}" /target_directory ; echo ;; esac; done
Уловка, которую я еще не видел здесь, которая не использует
extglob
,find
илиgrep
состоит в том, чтобы рассматривать два списка файлов как наборы и «различать» их, используяcomm
:comm
предпочтительнее,diff
потому что у него нет лишних хлопот.Это возвращает все элементы множества 1,
ls
, которые не также в наборе 2ls *Music*
. Это требует, чтобы оба набора были в отсортированном порядке для правильной работы. Нет проблем дляls
расширения и glob, но если вы используете что-то подобноеfind
, обязательно вызовитеsort
.Потенциально полезно.
источник
comm -23 <(ls) exclude_these.list
Одно решение для этого можно найти с помощью find.
Поиск имеет довольно много опций, вы можете получить довольно конкретные сведения о том, что вы включаете и исключаете.
Изменить: Адам в комментариях отметил, что это рекурсивно. параметры поиска mindepth и maxdepth могут быть полезны для управления этим.
источник
find -maxdepth 1 -not -name '*Music*'
подстановочногоВ следующих работах перечислены все
*.txt
файлы в текущем каталоге, кроме тех, которые начинаются с цифры.Это работает
bash
,dash
,zsh
и все другие POSIX совместимых оболочек.В первой строке шаблон
/some/dir/*.txt
заставитfor
цикл перебирать все файлы/some/dir
, имена которых заканчиваются на.txt
.Во второй строке оператор case используется для отсеивания нежелательных файлов. -
${FILE##*/}
Выражение удаляет любой начальный компонент имени dir из имени файла (здесь/some/dir/
), чтобы шаблоны могли сопоставлять только базовое имя файла. (Если вы только отсеиваете имена файлов на основе суффиксов, вы можете сократить это до$FILE
.)В третьей строке все файлы, соответствующие
case
шаблону[0-9]*
), будут пропущены (continue
оператор переходит к следующей итерацииfor
цикла). - Если вы хотите, вы можете сделать что-то более интересное здесь, например, пропустить все файлы, которые не начинаются с буквы (a – z)[!a-z]*
, или вы можете использовать несколько шаблонов, чтобы пропустить несколько видов имен файлов, например,[0-9]*|*.bak
чтобы пропустить файлы обоих.bak
файлов. и файлы, которые не начинаются с цифры.источник
*.txt
вместо просто*
). Исправлено сейчас.это сделало бы это, исключая именно «музыку»
это и это для исключения таких вещей, как музыка? * или *? музыка
источник
cp
руководства по MacOS имеет-a
опцию, но она делает что-то совершенно другое. Какая платформа поддерживает это?