Чи є така команда linux, як mv, але з regex?


41

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

чи є команда, яка дозволяє мені вказати шаблони перейменування?

Відповіді:


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?
mcandre

Перейменування версії Perl не може переміщувати файли з однієї файлової системи в іншу.
lilydjwg

bash one-line є корисним, особливо коли немає renameфункції (тобто зайнятий)
artm

10

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

rename .sql .php *.sql

Є також mmv(1), але мені невідомо, як це працює.


У Ubuntu та Debian (не впевнений у інших дистрибутивах) за замовчуванням /usr/bin/renameпосилання на посилання /usr/bin/prename, що займає регулярні вирази.
phaphink

5

День,

Ви також можете спробувати ввести

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

Або змусити його скористатись функцією regex

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

для розваги кодування оболонки. (-:


2
Це не вдається з файлами, що містять пробіли у своєму імені, тому будьте обережні. Ніколи неls слід аналізувати вихід .
slhck

THe 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]*

перераховує всі файли, що відповідають шаблону, в цьому випадку я шукаю файли з датою у назві файлу у формі "YYYYMMDD"

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: перша група захоплення - все ім'я файлу

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

^ 3: 3-я група захоплення - друга частина назви файлу - тут, дата як "РРРРММДД"

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

Sooooo .... якщо у мене є файл з іменем

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" для його виконання. Для того, щоб вперше побачити запропоновані рухи файлу БЕЗ власне їх переміщення, спочатку видаліть '| в кінці, і спробуйте так:

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-ї захопленої групи тощо.

ПОПЕРЕДЖЕННЯ ПРО БЕЗПЕКА: НІКОЛИ НЕ ПІДКЛЮЧАЙТЕ НІЩО, щоб "битися", ВСІХ, ЩО ВІДПОВІДНО ЗНАЙТІТЬ ВІДПОВІДЬ ...

Сподіваюсь, що це допоможе усунути деякі блокади :)


Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.