В качестве альтернативного подхода вам не нужны внешние программы, такие как rename
, basename
и т. Д. - все это может быть обработано в bash
расширении параметра: -
find SourceDir ... | while read -r f; do mv "$f" "TargetDir/$"; done
Расширение немного сложнее, поэтому вот что происходит:
- Файлы для перемещения находятся с
find
. - Каждое имя файла читается по очереди в
$f
. read -r
Параметр и двойные кавычки вокруг расширений обрабатывать странные имена, включая пробелы в именах файлов. mv
Команда перемещает имена, как a/b/c
в TargetDir/a_b_c
. - Целевое расширение заменяет каждый
/
на _
, но выглядит устрашающе, потому что /
является частью синтаксиса замещения. - Общая форма
$
, которая заменяет первый экземпляр old
на new
в расширении. - Здесь необходима форма
$
, которая заменяет каждый экземпляр old
by new
в расширении. - Чтобы
/
быть частью старой строки, ее необходимо экранировать следующим \/
образом $
: первый /
вводит синтаксис подстановки, второй /
определяет замену каждого, третий (экранированный) /
- старую строку, а финальный /
вводит новая строка ( _
).
Я не часто вижу эту форму расширения в скриптах, но об этом стоит знать, так как иногда она может быть очень полезна.
Есть некоторые имена файлов, которые будут нарушать это (встроенные символы новой строки и пробелы в начале или в конце, хотя есть два пути обхода последнего: -
- Используйте
read -r
вместо read -r f
и используйте REPLY
вместо f
. - Используйте
while f="$(line)"
вместо read -r f
.
Последний более аккуратный, но использует внешнюю программу line
, которая может быть недоступна на всех системах, хотя она может быть закодирована как функция:
line() { read -r; r=$?; echo "$REPLY"; return $r; }