想要为文件夹中的每个png制作txt文件


12

我有这个剧本

#!/bin/bash

folder='/home/data/mnist/training'

for filePng in $folder/*
do
touch $filePng.txt
done

它的工作原理是,对于名为的文件001.png,它创建001.png.txt而不是001.txt

我该如何修改?


4
引用变量是一个好习惯。Shell脚本是一种奇怪的语言,它会随着时间的推移而发展,而不是从一开始就经过精心设计,因此不幸的是,诸如此类的一些令人讨厌的事情变得必要。如果不引用变量,变量内容中的空格或星号会导致事情以奇怪的方式破坏。为了使脚本更加健壮,请始终在变量使用中使用双引号。在这里,您要说for filePng in "$folder"/*touch "$filePng".txt -请注意,只有在前面加引号时才引用它们$
Muzer

3
这看起来像XY问题……您为什么要尝试这样做?
杰罗姆·J

Answers:


16

您可以在basename此处使用命令:

touch "$folder/$(basename "$filePng" .png).txt"

请注意其他$folder/。这是必需的,因为basename命令会从中删除路径。


我可以建议您引用参数扩展和命令替换吗?
Tom Fenech

@TomFenech是的,引用整个字符串可能是个好主意。我编辑了答案。
Wayne_Yux

我不确定为什么要删除内部引号$filePng-它们也很有用。
Tom Fenech

1
不,因为$( )建立了新的报价上下文。
Tom Fenech

2
哦,您是对的-今天学到的新东西;-)
Wayne_Yux

31

您可以使用Shell的参数扩展功能删除现有扩展

${parameter%pattern}“模式”与“参数”的末尾匹配。结果是删除了最短匹配项的“参数”的扩展值。

因此,根据您的情况,将其替换$filePng.txt"${filePng%.png}.txt"


10

通过改变钢螺丝刀已经提到的内容-参数扩展-我们可以使用字符串替换来完成这项工作。此外,您应该引用变量。以下是您编辑的脚本。

#!/bin/bash

folder='/home/data/mnist/training'

for filePng in "$folder"/*
do
    touch "${filePng/.png/.txt}"
done

9

如果要创建的文件很多,那么一次“触摸”一个以上的文件是值得的,这样就不必为每个文件派生一个新进程(如果执行多个文件,则需要花费很多时间。一千次)。

选项1:模式替换+ xargs

此选项将一次提供touch命令的多个路径,通常为数千条或系统可以在单个命令行中容纳的任何路径。

find "$folder" -mindepth 1 -maxdepth 1 -name '*.png' -print0 |
sed -ze 's/\.png$/.txt/' |
xargs -r0 -- touch --

选项2:参数扩展+命令输出重定向

该选项根本不会运行touch,而是使用Bash / Bourne / POSIX Shell功能,而这些功能根本不需要子流程。

for f in "$folder"/*.png; do
    : >> "${f%.png}.txt"
done

4

如果您确定文件.png名中间没有位置,则可以使用带有参数扩展的数组:

pngs=( /path/to/pngs/*.png )
touch "${pngs[@]/.png/.txt}"

此存储所有的路径在结尾的文件.png的阵列中,然后使用扩展参数来创建的列表中.txt的文件,通过置换.png.txt上每一个。

请记住,如果您有太多文件而不能将它们全部作为同一调用的参数传递,则此操作将中断touch

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.