Как переименовать несколько файлов в каталоге одновременно


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-renameв арке Linux
Lesmana

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

3
@ danieldeveloper001 Вы использовали renameили prename? Смотрите мой комментарий выше. man {the command}списки авторов в конце.
ксеноид

2
Это работает только в системах, производных от Debian. Производные от Fedora системы имеют совершенно другую renameкоманду; см. unix.stackexchange.com/a/238862/135943
подстановочный

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 не делает.

(Команда переименования Perl имеет некоторые ограничения, но в данном конкретном случае эти ограничения не применяются.)

Что касается renameкоманды, показанной ранее, да, это работает, но тогда у вас есть вся эта путаница между двумя различными типами переименования и так далее. Если у вас есть правильный, отлично, но если нет, это тоже работает.

Если у вас нет команды perl-rename и вы не можете ее установить, вы можете просто сделать это:

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

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


Обычные реализации трубы будут иметь вилки.
Муру

Я имел в виду, «не будет разветвляться один раз для переименованного файла», в отличие от даже оболочки, где «mv» разветвляется / usr / bin / mv или что-то еще. Это связано с тем, что команда "rename" является внутренней командой perl, которая напрямую вызывает rename () в libc. Конечно, у него есть некоторые ограничения, но в этом конкретном примере эти ограничения не применяются.
ситарам

1
Это также относится и к renameкоманде ( top answer , также использует Perl), поэтому, возможно, вам следует добавить к ответу немного больше объяснений, чем просто «нет разветвлений».
Муру
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.