【问题标题】:Run script on multiple files在多个文件上运行脚本
【发布时间】:2017-10-21 00:17:50
【问题描述】:

我想对所有扩展名为 .xml 的一批文件执行script

受以前帖子的启发,我尝试了以下方法:

for file in *.xml; do ./script.sh <"$file"; done

for i in $(\ls -d *.xml)
do
    ./script.sh -i /path/*.xml -d /output_folder $i
done

这两个都多次运行脚本,但仅在该文件夹中的第一个 .xml 文件上运行。所以我最终得到了十几个输出文件,但它们都是 file1.txt、file1.txt_1、file1.txt_2 等。循环随机停止,有时在 3 次迭代后,有时在 28 次后。

任何帮助将不胜感激, 谢谢, TP

【问题讨论】:

  • 您希望脚本一次性获取所有文件,还是实际上希望它为每个 xml 文件运行一次?在一种形式中,您将每个文件重定向到脚本的stdin,而在另一种形式中,您正在传递参数,您希望采用哪种方式?
  • 了解 glob 的含义以及如何使用 find 命令。
  • ls -d 方法肯定是错误的,但另一种方法不是。如果for file in *.xml; do ./script.sh &lt;"$file"; done 真的遍历所有单独的 xml 文件。
  • 您确定您的script.sh 确实在关注标准输入上写入它的内容吗?最明显的原因是脚本没有使用它输入的内容,或者期望参数列表中的文件名而不是标准输入中的文件内容。
  • (由于您链接的 Interproscan 启动器只运行一个 Java 程序,读取它并没有说明它期望输入的任何有用信息。也就是说,它显然相当buggy -- 例如,如果您尝试向它传递一个带有空格的参数,则希望它被分成两个参数)。

标签: bash loops


【解决方案1】:
for f in /input_path/*.xml; do
  ./interproscan.sh -mode convert -f raw -i "$f" -d /output_path
done

【讨论】:

  • 是的,这似乎有效。优雅而简单。感谢您的帮助,主要是因为我学到了一些东西:)
【解决方案2】:

更简单安全的方法是这样的:

while IFS=  read -r -d $'\0'; do
    ./interproscan.sh -mode convert -f raw -i "$REPLY" -d /output_path
done < <(find . -iname "*.xml" -print0)

注意

1) 使用不区分大小写的 iname 进行搜索。

2) "$variable" 在文件名有空格时帮助你。

【讨论】:

  • 我也会尝试一下,一旦第一次测试完成。谢谢!
  • 这里,有一个病态的案例:touch $'file\nname.xml'。路径中唯一不能存在的字符是 NUL——换行符在很多常见的文件系统上都是合法的。因此,不能安全地使用换行符分隔的流来传输文件列表。
  • @Charles Duffy 所以,唯一的方法是使用空字符,就像我在 while 循环中所做的那样。
  • 是的——这对于所有可能的文件名都是安全的。 (就个人而言,我只使用-d '' 而不是-d $'\0',因为这两个解析为完全相同的字符串,但$'\0' 错误地向读者暗示shell 能够将带有NUL 文字的字符串表示为内容,但这是一个问题偏好/品味,而不是正确性。)
【解决方案3】:

您可以使用 find 的 -exec 选项来代替循环遍历文件。它将对每个文件执行命令,将{} 替换为文件的路径。请注意,您必须以 转义 分号 (\;) 结束命令。

这样的事情可能对你有用:

find . -name "*.xml" -exec ./script.sh -i /path/*.xml -d /output_folder {} \;

但您只能插入一次{},但也可以使用循环执行此操作:

xmlFiles=( $(find . -name "*.xml") )
for i in ${xmlFiles[@]}
do
   ./script.sh -i /path/*.xml -d /output_folder $i
done

【讨论】:

  • 同样的事情发生了。我猜我的脚本有些东西,而不是你建议的所有方法。对于脚本,我必须指定一个文件作为输入参数,但我使用 *.xml,所以也许这就是它处理文件全部错误的原因
  • 所以,这就是我使用参数运行脚本的确切方式: ./interproscan.sh -mode convert -f raw -i /input_path/*.xml -d /output_path 所以基本上,它需要.xml 文件并将它们转换为另一种称为“原始”的格式,指定为参数。
  • xmlFiles=( $(find . -name "*.xml") ) 有很多问题——它会将一个名称中带有空格的文件拆分为两个单独的文件名;将文件替换为名称中带有空格的星号,以获得当前目录中的文件列表;等等。如果您只想在当前目录中使用名为 *.xml 的文件,xmlFiles=( *.xml ) 会更可靠地完成这项工作。
  • 出于类似原因,应该是"${xmlFiles[@]}""$i"。报价很重要。
猜你喜欢
  • 2015-09-03
  • 2021-11-28
  • 2020-05-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-01-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多