Есть ли команда Linux, как Mv, но с регулярным выражением?

41

Например, я хочу mv (.*?).sql $1.php,

Есть ли команда, которая позволяет мне указать шаблоны переименования?

JoshRibs
источник

Ответы:

32

Как уже упоминали другие, renameэто хорошо, но прочитайте man-страницу ( man rename), прежде чем попробовать. Существует как минимум два совершенно разных инструмента, renameкоторые будут называться, и какой у вас будет зависеть от вашего дистрибутива. Называть их неправильно может быть опасно.

Вот справочная страница для версии на основе Perl Ларри Уолла, которая поставляется с Ubuntu. Вы даете ему выражение Perl, какrename 's/\.sql$/.php/' *.sql

Вот справочная страница для переименования, которая поставляется со старыми дистрибутивами Red Hat и CentOS. Использование простое подстановка строк, какrename .sql .php *.sql

Вы также можете использовать bash one-liner для обработки каждого файла по одному:

$ for f in *.sql; do mv -i "$f" "${f%%.*}.php"; done
Райан Брайт
источник
Может ли кто-нибудь загрузить бинарный файл Windows для переименования на основе Perl?
Макандре
Переименование версии Perl не может перемещать файлы из одной файловой системы в другую.
lilydjwg
Полезно использовать bash one-liner, особенно если у него нет renameфункции (например, busybox)
artm
10

Есть rename(1), который не использует регулярные выражения, но может решить вашу проблему:

rename .sql .php *.sql

Там тоже mmv(1), но я незнаком с тем, как это работает.

Адам Розенфилд
источник
В Ubuntu и Debian (не уверен в других дистрибутивах) /usr/bin/renameссылки /usr/bin/prenameпо умолчанию, что требует регулярных выражений.
ℝaphink
5

G'day,

Вы также можете попробовать войти

for i in $(\ls -d *.sql)
do
mv $i $(echo $i | sed -e 's/\.sql$/\.php/')
done

Или, чтобы заставить это использовать регулярное выражение, измените это немного, чтобы

for i in $(\ls -d | egrep -e '.*\.sql')
do
mv $i $(echo $i | sed -e 's/\.sql$/\.php/')
done

для немного веселья кодирования оболочки. (-:

Роб Уэллс
источник
2
Это не работает с файлами, которые содержат пробелы в названии, поэтому будьте осторожны. Никогда неls нужно разбирать вывод .
Slhck
Хотя sedпример неплохой.
яркая звезда
2

Будучи водопроводчиком, я люблю трубы :)

Примечание: этот ответ многословен - как новичок, я ценю, когда кто-то, кто знает, находит время, чтобы объяснить, поэтому я плачу «вперед». Если вы не новичок, прошу прощения за длину и многословие.

ls -1 *_201[67][0-9]* | sed -e 's/\(\(.\+\)[-_]\(201[67][0-9]\{4\}\)\([^.]\+\)\?\.[0-9a-z]\{2,3\}\)/mkdir -p \2\/\3; mv \1 \2\/\3\/\1/' | bash

Где:

ls -1 *_201[67][0-9]*

перечисляет все файлы, соответствующие шаблону, в этом случае я ищу файлы с датой в имени файла в форме «ГГГГММДД»

sed -e 's/\(\(.\+\)[-_]\(201[67][0-9]\{4\}\)\([^.]\+\)\?\.[0-9a-z]\{2,3\}\)/mkdir -p \2\/\3; mv \1 \2\/\3\/\1/'
#        : | |    |     |                  | |       |                    |:                                 :
#        : |^2....^    ^3..................^^4.......^                    |:                                 :
#        :^1..............................................................^:                                 :
#        /................filename.................pattern................./...mkdir...and....mv...command.../

^ 1: 1-я группа захвата - все имя файла

^ 2: 2-я группа захвата - 1-я часть шаблона имени файла

^ 3: 3-я группа захвата - вторая часть имени файла - здесь, дата в формате «ГГГГММДД»

^ 4: 4-я группа захвата - необязательная часть имени файла между датой и расширением и само расширение

Оооочень .... если у меня есть файл с именем

CallLog_555123412_20161231-214403.7z

...тогда

mkdir -p \2\/\3; mv \1 \2\/\3\/\1

на самом деле означает

# make directory and sub-directory
mkdir -p CallLog_555123412/20161231
# move file from current directory to sub-sub-directory just created
mv CallLog_555123412_20161231-214403.7z CallLog_555123412/20161231/CallLog_555123412_20161231-214403.7z

Обратите внимание, что выходные данные команды sed передаются в 'bash' для ее выполнения. Чтобы сначала увидеть предлагаемые перемещения файлов БЕЗ их фактического перемещения, сначала удалите '| bash 'в конце, и попробуйте так:

ls -1 *_201[67][0-9]* | sed -e 's/\(\(.\+\)[-_]\(201[67][0-9]\{4\}\)\([^.]\+\)\?\.[0-9a-z]\{2,3\}\)/mkdir -p \2\/\3; mv \1 \2\/\3\/\1/'

Это вообще не изменится, но вы увидите команду, которая будет выполнена, если вы запустите ее с помощью '| bash 'помечен на конце.

Это полезно, потому что вы можете создавать любые подкаталоги, которые вы хотите, из частей в имени файла, или что-либо еще, что вы добавляете к тексту «замены» в команде sed. Обратите внимание, что sed требует много экранирующих символов.

SED Regex скобки:

(...) требуется экранирование для группировки захвата -> \ (... \)

{m, n} требует экранирования для количественной оценки предыдущего объекта -> \ {m, n \}

/ требует экранирования в строке замены -> \ /

[...] НЕ требуется экранирование для классов персонажей

\ 1 в строке замены относится к 1-й захваченной группе и так далее ...

ПРЕДУПРЕЖДЕНИЕ О БЕЗОПАСНОСТИ: НИКОГДА НЕ ТРУПИТЕ НИЧЕГО, ЧТОБЫ «БЫТЬ», ЕСЛИ ВЫ ПОЛНОСТЬЮ НЕ ПОНИМАЕТЕ РЕЗУЛЬТАТ ...

Надеюсь, что это поможет устранить некоторые блокировки :)

skeetastax
источник
1

Установите mmv, затем сделайте это:

mmv "*.sql" "#1.php"
Gepsens
источник