Як перейменувати декілька файлів у каталозі одночасно


12

У мене в каталозі кажуть, /var/tmp/abcщо має 4 файли:

12345-ram-3e3r5-io9490-89adu9.csv
45434-dam-qwe35-to9490-43adu9.csv
11234-cam-yy3r5-ro9490-85adu9.csv
14423-sam-hh3r5-uo9490-869du9.csv

Я хочу перейменувати всі файли CSV (знайти всі файли та перейменувати їх) найкоротшим (можливо, однолінійним) способом до цього:

XXXXX-ram-3e3r5-io9490-89adu9.csv
XXXXX-dam-qwe35-to9490-43adu9.csv
XXXXX-cam-yy3r5-ro9490-85adu9.csv
XXXXX-sam-hh3r5-uo9490-869du9.csv

Відповіді:


15

rename -n 's/(\w+)/XXXXX/' *.csv

видалити, -nколи щасливий.


2
Для підходящої версії rename. Я припускаю, що це Ларрі Уолл rename, з renameпакету Debian і похідної (і IIRC prenameдля систем переконання RedHat). Дуже корисний інструмент.
ксеноїд

2
perl-renamein arch linux
lesmana

1
@SHawarden, я намагався виконати команду і прочитати відповідну частину сторінки man, щоб зрозуміти шаблон заміни, але, додаючи verboseпрапор, він нічого не видає і не виконує зміни файлу, навіть якщо поточний шлях має файли з іменами, схожими на 12345_foo.csv. Чи потрібно мені виконувати якесь додаткове завдання, щоб воно працювало (зараз у Fedora 30)? Це більш чистий підхід, ніж циклічне. Спасибі заздалегідь!
danieldeveloper001

3
@ danieldeveloper001 Ви використовували renameабо prename? Дивіться мій коментар вище. man {the command}перераховує авторів наприкінці.
ксеноїд

2
Це працює лише на похідних Debian системах. Системи, що походять від Fedora, мають зовсім іншу renameкоманду; дивіться unix.stackexchange.com/a/238862/135943
Wildcard

11

Спробуйте:

for f in *.csv; do mv -i -- "$f" "XXXXX-${f#*-}"; done

Як це працює:

  • for f in *.csv; do

    Це запускає цикл для всіх *.csvфайлів.

  • mv -i -- "$f" "XXXXX-${f#*-}"

    Це перейменовує файли, як потрібно, інтерактивно запитуючи перед тим, як перезаписати будь-який файл.

  • done

    Це позначає кінець циклу.

Приклад:

$ ls -1
11234-cam-yy3r5-ro9490-85adu9.csv
12345-ram-3e3r5-io9490-89adu9.csv
14423-sam-hh3r5-uo9490-869du9.csv
45434-dam-qwe35-to9490-43adu9.csv
$ for f in *.csv; do mv -i -- "$f" "XXXXX-${f#*-}"; done
$ ls -1
XXXXX-cam-yy3r5-ro9490-85adu9.csv
XXXXX-dam-qwe35-to9490-43adu9.csv
XXXXX-ram-3e3r5-io9490-89adu9.csv
XXXXX-sam-hh3r5-uo9490-869du9.csv

4

Мені сподобався маленький виклик, який ви опублікували, тому ось моє рішення. Я припускаю, що всі ваші файли починаються з 5 цифрових символів, тому використовуючи команду cut, щоб замінити початкові числові файли на "XXXXX".

Нижче файли перед командою.

-rw-rw-r--. 1 daniel daniel 0 May 13 23:18 11111_bar_file.csv
-rw-rw-r--. 1 daniel daniel 0 May 13 22:54 12345_baz_file.csv
-rw-rw-r--. 1 daniel daniel 0 May 13 22:54 67890_foo_file.xml

Нижче - команда одного вкладиша.

for src in *.csv; do dst=XXXXX$(echo $src| cut -c6-); mv $src $dst; done;

Нижче - файли після команди.

-rw-rw-r--. 1 daniel daniel 0 May 13 22:54 67890_foo_file.xml
-rw-rw-r--. 1 daniel daniel 0 May 13 22:54 XXXXX_bar_file.csv
-rw-rw-r--. 1 daniel daniel 0 May 13 23:18 XXXXX_baz_file.csv

Це те, що ви шукаєте? :)

Список літератури:

Прокручування через командний вихід у bash

Підрядки в базі


2
Bash може робити подібні маніпуляції з рядками, не потрібно розпалювати новий процес для кожного, будь ласка, іншу відповідь про те, як.
chx

1
@chx, вже побачила інші відповіді та отримала з неї трохи знань, але дякую, що вказали на них. Чи хочете ви детальніше розглянути no need to fork a new process for each?
danieldeveloper001

3
cutє окремим двійковим кодом ( /usr/bin/cut), і при його використанні витрачається більше ресурсів, ніж використання вбудованих оболонок.
chx

2
Я бачу, це насправді має значення, якщо намір перейменує багато файлів. Дякую за роз’яснення!
danieldeveloper001

1

немає виделок:

ls | perl -lne '$suf=substr($_,6); rename $_, "XXXXX-$suf"'

Коли ви використовуєте цикл оболонки, mvроздвойте один раз на файл. renameКоманда Перла не робить.

(Команда перейменування Perl має деякі обмеження, але в цьому конкретному випадку ці обмеження не застосовуються.)

Що стосується renameкоманди, показаної раніше, так, це працює, але тоді у вас є все це плутанина між двома різними видами перейменування тощо. Якщо у вас є правильний, чудово, але якщо ні, це теж працює.

Якщо у вас немає команди perl-перейменувати і не можете її встановити, ви можете просто зробити це:

ls | perl -lne '$old=$_; s/(\w+)/XXXXX/; rename $old, $_'

Як бачимо, для цього використовується та сама підміна, яка вказана у верхній відповіді. Звичайно, Perl перейменування є і інші навороти (верхній відповідь було сказано, -nвже, тобто -0, -fі так далі), і тим більше з них вам потрібно, тим більше ви повинні встановити , що замість того , щоб додати власні таким чином , .


Звичайні реалізації труби матимуть вилки.
муру

Я мав на увазі, "не буде перейменовано один раз на файл, який буде перейменований", на відміну від навіть оболонки, де "mv" forks / usr / bin / mv чи що завгодно. Це тому, що команда "перейменувати" - це внутрішня команда perl, яка безпосередньо викликає rename () у libc. Звичайно, у нього є деякі обмеження, але в цьому конкретному прикладі ці обмеження не застосовуються.
ситарам

1
Це також стосується renameкоманди ( головна відповідь , також використовується Perl), тому, можливо, вам слід додати трохи більше пояснень, ніж просто "без вил" у відповідь.
муру
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.