2

我正在尝试运行一个简单的 bash 脚本,但我正在努力解决如何使条件失效。任何指针。循环说。我想取消一个条件,这样当 gdalinfo 无法打开图像时,它会将该特定文件复制到另一个位置。

for file in `cat path.txt`; do gdalinfo $file;done

在打开图像时效果很好,并且还显示了哪些无法打开。
错误的代码是

for file in `cat path.txt`; do gdalinfo $file && echo $file; else cp $file /data/temp
4

2 回答 2

6

一次又一次,一次又一次——又是无数次……

不要使用类似的结构

for file in `cat path.txt`

或者

for file in `find .....`
for file in `any command what produces filenames`

因为当文件名或路径包含空格时,代码会立即中断。永远不要将它用于任何产生文件名的命令。不好的做法。很坏。它是不正确的、错误的、错误的、不准确的、不精确的、不精确的、有缺陷的、错误的。

正确的形式是:

for file in some/*   #if want/can use filenames directly from the filesystem

或者

find . -print0 | while IFS= read -r -d '' file

或(如果您确定没有文件名包含换行符)可以使用

cat path.txt | while read -r file

但这里cat是没用的,(真的 -将文件复制到 STDOUT的命令没用的)。你应该改用

while read -r file
do
   #whatever
done < path.txt

它更快(不会像每个管道那样分叉一个新进程)。

如果文件名也包含空格,上面while的 s 会将正确的文件名填充到变量中。不会file_ 时期。呃。我的天啊。for

出于同样的原因,使用"$variable_with_filename"而不是纯。$variable_with_filename如果文件名包含空格,则任何命令都会将其误解为两个文件名。这可能不是,你也想要什么..

因此,将任何包含文件名的 shell 变量用双引号括起来。(不仅是文件名,还有任何可以包含空格的东西)。"$variable"是正确的。

如果我理解正确,您希望将文件复制到返回错误/data/temp时。gdalinfo

while read -r file
do
   gdalinfo "$file" || cp "$file" /data/temp
done < path.txt

不错,简短且安全(至少如果您的 path.txt 确实每行包含一个文件名)。

也许,你想多次使用你的脚本,因此不要把里面的文件名拿出来,而是把脚本保存在一个表格中

while read -r file
do
   gdalinfo "$file" || cp "$file" /data/temp
done

并像这样使用它:

mygdalinfo < path.txt

更通用...

也许,您只想显示gdalinfo返回错误的文件名

while read -r file
do
   gdalinfo "$file" || printf "$file\n"
done

如果您将其更改为printf "$file\n"printf "$file\0"则可以安全地在管道中使用脚本,因此:

while read -r file
do
   gdalinfo "$file" || printf "$file\0"
done

并将其用作例如:

 mygdalinfo < path.txt | xargs -0 -J% mv % /tmp/somewhere

豪。

于 2013-07-19T11:35:26.117 回答
1

你可以说:

for file in `cat path.txt`; do gdalinfo $file || cp $file /data/temp; done

/data/temp如果 gdalinfo 无法打开图像,这会将文件复制到。

如果除了在失败的情况下复制文件名之外还想打印文件名,请说:

for file in `cat path.txt`; do gdalinfo $file || (echo $file && cp $file /data/temp); done
于 2013-07-19T11:07:43.360 回答