Пакетное переименование файлов в командной строке и Xargs

Итак, у меня есть следующая структура:

.
..
a.png
b.png 
c.png

я запустил команду, чтобы изменить их размер

ls | xargs -I xx convert xx -resize xx.jpg

Теперь мой dir выглядит так

.
..
a.png.jpg
a.png
b.png.jpg
b.png
c.png.jpg
c.png

первый вопрос: как переименовать файл, чтобы у меня было только одно расширение. Не два. (в принципе, как я могу очистить свою первоначальную ошибку)?

Второй вопрос: в будущем, используя xargs, как изменить расширение файла simular на second command?

6 ответов


как переименовать файл, чтобы у меня было только одно расширение.

cd dir/with/messedup/files

for file in *.png.jpg; do
  mv "$file" "${file%.png.jpg}.jpg"
done

в будущем, используя xargs, как изменить расширение файла simular на вторую команду?

насколько мне известно,это невозможно. Лучший способ сделать это - использовать for-loop с подстановкой параметров, как показано выше:

for file in *.png; do
  convert "$file" -resize "${file%.png}.jpg"
done

если у вас есть файлы в подкаталогах, которые вы хотите преобразовать, затем вы можете трубить find до while read петли:

find . -type f -name '*.png' |
while read file; do
  convert "$file" -resize "${file%.png}.jpg"
done

Примечание: это вообще считается плохая идея использовать выход ls в shell-скрипт. Хотя ваш пример мог бы работать нормально, есть много примеров, где это не так. Например, если в ваших именах файлов появились новые строки (что позволяет unix), ls вероятно, не избежать для тебя. (Это на самом деле зависит от вашей реализации, которая еще одна причина не использовать ls в скриптах; это поведение сильно варьируется от одного окна к другому.) Вы получите более последовательные результаты, если вы используете find во время чтения или цикла подстановки файлов (например,*.png) в цикле for.


Это также можно сделать с xargs и sed изменить расширение файла.

ls | grep \.png$ | sed 'p;s/\.png/\.jpg/' | xargs -n2 mv

вы можете распечатать исходное имя файла вместе с тем, что вы хотите, чтобы имя файла. Затем попросите xargs использовать эти два аргумента в команде move. Для однострочного я также добавил grep, чтобы отфильтровать что-либо не *.PNG-файл.


опаздывает на вечеринку, но вот как вы можете переименовывать файлы с помощью xargs. Скажем, у вас есть куча файлов с именем fileN.формат SVG.png, и вы хотите назвать их fileN.png, где N может быть рядом целых чисел:

ls *.svg.png | xargs basename -s .svg.png | xargs -I {} mv {}.svg.png {}.png

первый xargs использует basename для удаления обоих .svg и .png, чтобы получить просто filenameN. Второй xargs получает это голое имя и использует замену для переименования файла.


чтобы очистить вашу ошибку, попробуйте rename утилиты. Проверьте manpage для деталей.

в вашем случае, вы могли бы сделать rename '.png.jpg' '.jpg' ./* если ваш текущий каталог устанавливается должным образом.

так как у вас есть convert доступно, я предполагаю, что у вас есть mogrify тоже (imagemagick suite). Всякий раз, когда я хочу это сделать, я копирую файлы в другой каталог и использую . Обычно мне это нужно только для изменения размера, но если вы измените формат изображения,mogrify будет обрабатывать имена файлов (создание новых файлов с правильными именами файлов).

вы бы использовали его как mogrify -format jpg -resize [size] ./*.png. Я не уверен, что -resize без аргументов геометрии должен делать. Это не документировано и не работает на моей машине.

как рассуждал Тим пот, я не думаю, что вы можете заставить xargs обрабатывать имена файлов и расширения отдельно.


Я опоздал на эту вечеринку примерно на 3 года, у меня просто была аналогичная проблема, которую я выяснил сам. У меня был список png-файлов, которые я преобразовал с помощью inkscape, потому что поддержка svg ImageMagick плохая.

Я первоначально преобразовал их, сделав:

find . -name "*.svg" -exec inkscape {} --export-png={}.png

что, конечно, привело к той же проблеме, что и выше.

file1.svg
file1.svg.png
file2.svg
file2.svg.png
file3.svg
file3.svg.png
file4.svg
file4.svg.png

Я хотел переименовать *.формат SVG.png to *.png, это то, что я поранился...

find . -name "*.svg.png" -print0 | sed 's/.svg.png//g' | xargs -0 -I namePrefix mv namePrefix.svg.png namePrefix.png

это три вещи:

  1. найти в этом каталоге файлы с именем *.формат SVG.png, - print0 печатает на стандартный вывод
  2. sed изменяет стандартный вывод, в основном swap .формат SVG.PNG с ничего, так что я хотел сделать: файл1/файл2/файл file3/файл file4
  3. xargs -0 чтобы получить данные из sed, - я ссылаюсь на имя файла без расширения, а затем MV оригинальное имя файла на новое имя файла. Слово namePrefix не является чем-то особенным, просто хотел сделать это четкий.

редактировать

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

rename 's/svg\.png/.png/' *

мое решение похоже на многие решения xarg и особенно похоже на Schleis.

разница здесь - полная манипуляция регулярным выражением со ссылками на совпадения и командами sed, которые правильно игнорируют файлы, которые не совпадают, поэтому вам не нужно предварительно фильтровать свой список.

это также безопасно для файлов с пробелами и оболочкой meta.

изменить в замене к любому пожеланному расширение.

ls |
sed -nE 's/Rick\.and\.Morty\.(S03E[0-9]{2})\..*(\.[a-z0-9]{3})/"&" "Rick and Morty "/;T;p' |
xargs -n 2 mv

объяснение

на -n arg tell sed не печатать ничего по умолчанию,T команда говорит пропустить до конца сценария, если предыдущий s команда не сделала замену, печать шаблонов (только если s команда матчи).

на & в замене есть ссылка на содержимое исходного соответствия имени файла.

если заменить mv in команда с bash -c 'echo "run($#) $@"' bash тогда мы можем видеть количество раз mv будет вызываться, а с параметром count и value:

$ ls |
  sed -nE 's/Rick\.and\.Morty\.(S03E[0-9]{2})\..*(\.[a-z0-9]{3})/"&" "Rick and Morty "/;T;p' |
  xargs -n 2 bash -c 'echo "run($#) $@"' bash
run(2) Rick.and.Morty.S03E02.720p.HDTV.x264-BATV.mkv Rick and Morty S03E02.mkv
run(2) Rick.and.Morty.S03E03.720p.HDTV.x264-BATV.mkv Rick and Morty S03E03.mkv
run(2) Rick.and.Morty.S03E04.720p.HDTV.x264-BATV.mkv Rick and Morty S03E04.mkv
run(2) Rick.and.Morty.S03E05.HDTV.x264-BATV[ettv].mkv Rick and Morty S03E05.mkv
run(2) Rick.and.Morty.S03E06.720p.HDTV.x264-BATV.mkv Rick and Morty S03E06.mkv
run(2) Rick.and.Morty.S03E06.HDTV.x264-BATV.mkv Rick and Morty S03E06.mkv
run(2) Rick.and.Morty.S03E07.720p.HDTV.x264-BATV[ettv].mkv Rick and Morty S03E07.mkv
run(2) Rick.and.Morty.S03E08.720p.HDTV.x264-BATV.mkv Rick and Morty S03E08.mkv
run(2) Rick.and.Morty.S03E09.720p.HDTV.x264-BATV.mkv Rick and Morty S03E09.mkv
run(2) Rick.and.Morty.S03E10.720p.HDTV.x264-BATV.mkv Rick and Morty S03E10.mkv