36

所以,我有以下结构:

.
..
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 的扩展名更改为第二个命令?

4

10 回答 10

73

xargs这也可以通过sed更改文件扩展名来完成。

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

您可以打印原始文件名以及您想要的文件名。然后让 xargs 在 move 命令中使用这两个参数。对于单行,我还添加了一个 grep 来过滤掉任何不是 *.png 文件的内容。

于 2013-10-15T14:50:41.840 回答
24

我如何重命名文件,以便我可以只有一个扩展名。

cd dir/with/messedup/files

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

将来,使用 xargs,如何将文件 simular 的扩展名更改为第二个命令?

据我所知,这是做不到的。最好的方法是使用带有参数替换的 for 循环,就像上面的那样:

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

注意:通常认为在 shell 脚本中使用 的输出是个坏主意。ls虽然您的示例可能效果很好,但有很多示例无法正常工作。例如,如果您的文件名中碰巧有换行符(unix 允许),ls则可能不会为您转义。(这实际上取决于您的实现,这是不在ls脚本中使用的另一个原因;它的行为从一个框到下一个框变化很大。)如果您find在 while-read 循环或文件通配符(例如*.png)在 for 循环中。

于 2012-06-10T20:16:28.950 回答
17

聚会迟到了,但这里是您可以使用 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 接收该裸名并使用替换来重命名文件。

于 2015-05-09T06:20:41.873 回答
6

要清除您的错误,请尝试使用该rename实用程序。查看手册页以获取详细信息。

在您的情况下,rename '.png.jpg' '.jpg' ./*如果您的当前目录设置正确,您会这样做。

既然你convert有空,我假设你也有mogrifyimagemagick套件)。每当我想这样做时,我都会将文件复制到不同的目录中并mogrify改为使用。我通常只需要它来调整大小,但如果您也更改图像格式,mogrify将处理文件名(使用正确的文件名制作新文件)。

你会用它作为mogrify -format jpg -resize [size] ./*.png. 我不确定-resize没有几何参数应该做什么。它没有记录,也不能在我的机器上运行。

正如 Tim Pote 所说,我认为您不能让 xargs 分别处理文件名和扩展名。

于 2012-06-10T21:05:13.297 回答
5

我参加这个聚会迟到了大约 3 年,我只是遇到了一个类似的问题,我自己也发现了。我有一个使用 inkscape 转换的 png 文件列表,因为 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

这做了三件事:

  1. 在此目录中找到名为 *.svg.png 的文件,将 -print0 打印到标准输出
  2. sed 修改标准输出,基本上交换 .svg.png 什么都没有,所以我会得到:file1/file2/file3/file4
  3. xargs -0 从 sed 获取数据,-I 引用不带扩展名的文件名,然后将原始文件名 mv 引用为新文件名。namePrefix 这个词并没有什么特别之处,只是想说明一下。

编辑

我现在意识到这是最复杂的方法。可以简单地使用重命名命令。

rename 's/svg\.png/.png/' *
于 2015-01-05T18:24:37.773 回答
3

在对类似任务进行一些调查后,这是我的代码:

find . -maxdepth 1 -name '*.png' -print0 | sed 's/.png//g' | xargs -0 -I% -n 1 -P 8 convert -quality 100 %.png %.jpg

推理:

  • 重命名不会压缩文件(所以使用convert代替mv
  • ls \.png$ | xargs不会处理路径/文件名中的空格
  • find .将在子文件夹中搜索,所以使用-maxdepth 1
  • convert不使用可用的 CPU,所以-P8(或-P other
  • sed没有'g'最后不会替换所有文件(只有一个)
  • sed 's/.png//g'不会留下任何扩展名(basename 也可以工作,但之后没有-print0
  • parallel- 可能更好的解决方案,但不适用于我的 Ubuntu 18.04 bash 4.4
  • %是用于替换的最小通用符号(与 相比{} xx namePrefix
  • -n2参数适用,xargs但不能正常使用-print0n要获取和传递的条目数xargs
  • -quality 100默认魔法质量是 92(这很好),这里是 100% 以避免丢失任何东西
于 2019-03-06T01:54:39.673 回答
1

我的尝试来自:https ://www.tecmint.com/linux-image-conversion-tools/

ls -1 *.png | xargs -n 1 bash -c 'convert "$0" "${0%.png}.jpg"'

使用并行

parallel convert '{}' '{.}.jpg' ::: *.png
于 2019-01-10T17:32:06.630 回答
1

我的解决方案类似于许多 xarg 解决方案,尤其类似于 Schleis 的解决方案。

这里的区别是一个完整的正则表达式操作,带有匹配引用,以及正确忽略不匹配文件的 sed 命令,因此您不需要预先过滤您的列表。

这对于带有空格和 shell 元数据的文件也是安全的。

\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

解释

-narg 告诉 sed 默认情况下不打印任何内容,如果前一个命令没有进行替换,该命令说T跳到脚本的末尾,该命令打印模式空间(仅在命令匹配时才命中)。sps

替换中的&是对原始文件名匹配内容的引用。

如果我们mv在命令中替换为bash -c 'echo "run($#) $@"' bashthen 我们可以看到mv将被调用的次数,以及参数 count 和 value:

$ 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($#) $@"' 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
于 2018-02-17T19:58:43.057 回答
0

第一次回答,希望不会太惨。

我遇到了同样的麻烦,我设法结合Schleis 答案adrianN评论解决了它。问题在于某些带有空格字符的文件或 ext4 中允许的其他特殊文件。
它应该增加使用任何 UTF8 文件名的能力。就这个:

find . -type f -iname \*.png.jpg -print0 | sed -z 'p;s/\.png\.jpg/\.jpg/' | xargs -0 -n2 mv

我读过(不记得在哪里)过去 sed(或 xarg?)在处理空字符时遇到了麻烦。好像就没有这种情况了。

我在下面为像我这样喜欢了解他们所做的事情而不仅仅是复制一些答案的人添加了一些解释。;-)

命令参数:

寻找 。:在当前目录中查找
-type f :常规文件(例如:不是设备、目录等)
-iname :根据文件名搜索,但匹配不区分大小写。以防万一您的图片软件写“PNG”而不是“png”
-print0 :分隔由 NULL 字符找到的内容

sed -z :将空字符视为要处理的不同文本元素的唯一分隔符;对于收到的文本和修改后的文本
p :写入第一个收到的行
s/.png.jpg/.jpg/ :用 .jpg 替换 .png.jpg 并写入

xargs -0 :输入项以空字符而不是其他任何字符终止
-n2 :将从 sed 接收到的两个参数发送到 mv

每个命令的作用:

寻找 :

file1.png.jpgNULLfile2.png.jpgNULLfile3.png.jpgNULLfile4.png.jpg

sed

file1.png.jpgNULLfile1.jpgNULLfile2.png.jpgNULLfile2.jpgNULLfile3.png.jpgNULLfile3.jpgNULLfile4.png.jpgNULLfile4.jpg

xargs

mv file1.png file1.jpg  
mv file2.png file2.jpg  
mv file3.png file3.jpg  
mv file4.png file4.jpg  
于 2022-02-23T05:34:11.040 回答
-1

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

我喜欢使用以下命令

find ./xx -name "*.png" -type f|while read FILE; do
  mv "$FILE" "$(echo $FILE|sed -e 's/.png$/.jpg/')";
done
于 2018-12-08T07:51:22.937 回答