Пакетное переименование файлов в командной строке и Xargs - программирование
Подтвердить что ты не робот

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

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

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

Я выполнил команду для изменения их размера

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

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

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

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

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

4b9b3361

Ответ 1

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

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 в оболочке script. Хотя ваш пример, возможно, сработал хорошо, есть много примеров, где это не так. Например, если ваши имена файлов имели в них новые строки (что позволяет unix), ls, вероятно, не удастся избежать этих действий для вас. (Это действительно зависит от вашей реализации, что является еще одной причиной не использовать ls в скриптах, это поведение сильно варьируется от одного окна к другому.) Вы получите более последовательные результаты, если вы либо используете find через некоторое время (или *.png) в цикл цикла.

Ответ 2

Это также можно сделать с помощью xargs и sed, чтобы изменить расширение файла.

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

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

Ответ 3

Поздняя вечеринка, но здесь вы можете переименовывать файлы с 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 получает это голое имя и использует замену для переименования файла.

Ответ 4

Чтобы очистить вашу ошибку, попробуйте утилиту rename. Подробнее см. Man-страницу.

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

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

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

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

Ответ 5

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

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

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 в *.png, это то, с чем я столкнулся...

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

Это делает три вещи:

  • найдите в этом каталоге файлы с именем *.svg.png, print-print0 на стандартный вывод
  • sed изменяет стандартный вывод, в основном заменяет .svg.png ничем, поэтому я бы получил: file1/file2/file3/file4
  • xargs -0, чтобы получить данные от sed, -I ссылается на имя файла без расширения, а затем на исходное имя файла mv на новое имя файла. Слово namePrefix не является чем-то особенным, просто хотел прояснить.

ИЗМЕНИТЬ

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

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

Ответ 6

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

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

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

Замените \2 в замене на любое желаемое расширение.

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

объяснение

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

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

Если мы заменим mv в команде на bash -c 'echo "run($#) [email protected]"' bash то увидим, сколько раз будет вызвана mv, а также количество и значение параметра:

$ ls |
  sed -nE 's/Rick\.and\.Morty\.(S03E[0-9]{2})\..*(\.[a-z0-9]{3})/"&" "Rick and Morty \1\2"/;T;p' |
  xargs -n 2 bash -c 'echo "run($#) [email protected]"' 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

Ответ 8

find./xx -name "*.png" -print0 |sed 's/.png$//g'|xargs -0 -I% mv %.png %.jpg