Шаблон подстановочных знаков *.avi
расширяется оболочкой, которая запускает find
перед запуском find
, поэтому его действие зависит от того, есть ли файлы *.avi
в текущем каталоге или нет. См. find not recursive when file at top для получения дополнительных пояснений. Чтобы расширить *.avi
в подкаталогах,вам нужно будет сделать три вещи по-разному :указать шаблон, чтобы исходная оболочка не расширяла его; организовать запуск дополнительной оболочки в каждом подкаталоге для выполнения подстановочного расширения; и искать каталоги только с помощью команды find
, а не любого типа файла.
Кроме того, ваш код вызывает rename
для каждого файла на любом уровне в текущем каталоге, включая сами подкаталоги, через {} +
. Итак, rename
работает с каталогами, а не только с обычными файлами.
Кроме того, в вашем коде Perl есть синтаксическая ошибка.
autoload -Uz zmv # best in ~/.zshrc
zmv -n '(**/)(*.avi)(#qD^/)' '$1${2//[^a-zA-Z0-9._-]/_}'
^/
— выбрать любой тип файла, кроме каталога . Замените на .
только для обычных файлов . -n
для работы всухую -. Удаляйте, когда счастливы.
find
иrename
С вариантами rename
на основе perl -и реализацией find
, поддерживающей-execdir
:
LC_ALL=C find. -depth -name '*[!a-zA-Z0-9._-]*.avi' ! -type d -execdir \
rename 's/[^a-zA-Z0-9._-]/_/g' {} +
При таком подходе есть несколько предостережений:
rename
экземпляр на каталог, содержащий файлы для переименования (один rename
на файл с некоторыми find
реализациями/версиями, где -execdir... {} +
фактически совпадает с -execdir... {} \;
.(zmv
запускает один mv
для каждого файла, но вы можете сделать mv
встроенным с помощью zmodload zsh/files
, чтобы ускорить его ). -execdir
find
запускает команду в каталоге , который содержит эти файлы, и передает команде путь относительно этого каталога. Некоторые find
реализации (GNU )добавляют префикс ./
к файлам, некоторые — нет. Некоторые варианты rename
принимают опции после выражения Perl, что означает, что если у вас есть файл, имя которого начинается с -
, это может вызвать проблемы.LC_ALL=C
для -name
для работы, даже если имена файлов содержат последовательности байтов, которые в противном случае не сформировали бы допустимые символы в локали. rename
наследует это и в любом случае в большинстве вариантов работает только с ASCII. Однако это означает, что он заменит многобайтовые символы -на столько _
, сколько байтов содержит символ. Например, он переименует UTF -8 stéphane
в st__phane
вместо st_phane
. zsh
подходит, потому что он преобразует как многобайтовые символы -, так и все байты, которые не могут быть декодированы в символы, в один _
символ каждый. zsh
's zmv
, он не будет выполнять проверки работоспособности (например, 2 файла не будут иметь одинаковое имя, например a+b.avi
иa@b.avi
)до начала переименования. Однако rename
не должен перезаписывать существующие файлы. ~
— это ярлык для вашего домашнего каталога, но только когда он появляется в начале строки вне кавычек . Начало правой -части оператора присваивания является началом строки, поэтому env1=~/Dropbox/.env
будет работать как (или env1=~"/Dropbox/.env"
или любое количество вариантов ). Он устанавливает env1
в /home/roach/Dropbox/.env
. Но env1="~/Dropbox/.env"
устанавливает env1
в точную строку ~/Dropbox/.env
, которая в качестве имени файла выглядит внутри каталога с одним -символьным именем ~
в текущем каталоге.
Тильда — это аббревиатура, а не подстановочный знак. $env1
вне кавычек расширяет подстановочные знаки в значении env1
, но не расширяет тильду, потому что тильда не является подстановочным знаком.
Вы также можете использовать env1="$HOME/Dropbox/.env"
. Это эквивалентно env1=~/Dropbox/.env
. Символ$
(доллар )имеет особое значение внутри двойных кавычек (это то же значение, что и вне кавычек ):он начинает подстановку переменной (или команду или арифметическую подстановку ). С другой стороны, символ~
(тильда )является обычным символом, если он заключен в кавычки, даже в двойные кавычки.
Что касается псевдонима, причина, по которой он не работает в сценарии bash, заключается в том, что bash по умолчанию не расширяет псевдонимы в сценариях.Он не будет работать ни в одном сценарии, если вы не включите или не получите определение псевдонима в этом сценарии, поскольку псевдонимы являются свойством каждого экземпляра оболочки. Они не являются частью среды процесса.
Причина, по которой псевдоним вообще работает во втором скрипте, заключается в том, что dotdrop сама расширяет тильду, когда читает значение конфигурации.