使用文件中的参数(文件名)多次运行命令?

使用文件中的参数(文件名)多次运行命令?

我有一个文件,其中包含一长串文件名(带有完整路径)。我还有一个程序想要多次运行,使用此列表中的一个和一个文件名作为参数。遗憾的是,我想运行的程序是一个自制的脚本;所以只能采取一次输入文件名,并且它不能接受来自标准输入(如文件名列表) - 因此不可能进行管道或输入重定向。

我需要的是一个将运行的命令其他命令(我的脚本),使用文件中的行作为参数。

类似于find-action -exec...( find . -name "*.txt" -exec command \;)。我想我其实可以在这里使用find,但我想对输入文件进行排序......

所以我需要的是这样的:

for_each_command1 -f 文件列表 -c './my_command {}'
for_each_command2 -f 文件列表 -exec ./my_command {} \;
for_each_command3 -c './my_command {}'

我处理此类任务的常用方法是sed- 不幸的是,有很多开销而且不太漂亮(但它工作...):

$ wc -l 文件列表 第232章 $ for (( i=1;我愿意 > ./my_command "`sed -n "${i}p" 文件列表`" > 完成

那么是否有内置的命令或 shell 来处理这样的事情呢?

答案1

方便,xargs -I完全符合您的要求:

$ xargs <my_file_list.txt -I filename ./my_command "filename"
-I replace-str
    Replace occurrences of replace-str in the initial-arguments with names read
    from standard input.
    Also, unquoted blanks do not terminate input items;
    instead the separator is the newline character.
    Implies -x and -L 1.

这意味着它只需要一个以换行符分隔的输入行,并将其作为单个参数调用您的命令。除了换行符之外,没有任何内容被视为分隔符,因此空格和其他特殊字符都可以。

请注意,如果您想在文件名中允许换行符,则 nul 终止符(根据通配符的答案)也将在文件中起作用。

答案2

我假设您的文件列表存储在名为“filelist.txt”的文件中,每个文件名位于一行中。然后您可以使用每一行作为参数来调用脚本,如下所示:

while read name; do
  ./yoursrcipt.sh "$name"
done <filelist.txt

答案3

我通常更喜欢便携式(POSIX)解决方案,但是简单、明显这里的答案是使用 GNU 扩展来让你的生活更轻松:

find . -type f -name '*.txt' -print0 | sort -z | xargs -n1 -r0 ./mycommand

这使用空字节作为文件名之间的分隔符,这很重要,因为文件名可以包含任何字符,包括换行符。

(斜杠也被保留,因为它们是路径组件分隔符,但在这种情况下这并不重要,因为您不能将它们用作文件分隔符。)

答案4

$ cat baard.in
/path/to/some space file
/some   tabbed/some     tabbed  file
/path to/genericfile
/path/to/regular.file
/path/to/exciting!/file!
/path/to/(parenthetical)/file.txt

$ cat my_command
#!/bin/sh
printf "my_command: %s\n" "$1"

由于 awk 已经解析行,因此您可以使用它对每条记录调用命令,请小心引用参数:

$ awk '{system("./my_command '\''" $0 "'\''");}' < baard.in
my_command: /path/to/some space file
my_command: /some       tabbed/some     tabbed  file
my_command: /path to/genericfile
my_command: /path/to/regular.file
my_command: /path/to/exciting!/file!
my_command: /path/to/(parenthetical)/file.txt

但是,如果输入中存在单引号,则 awk 命令会失败,例如:

/books/Hitchhiker's Guide to the Galaxy.epub

如果你有 bash 可用,你可以使用:

$ readarray -t paths < baard.in
$ for((i=0;i < ${#paths[*]}; i++)); do ./my_command "${paths[i]}"; done
my_command: /path/to/some space file
my_command: /some       tabbed/some     tabbed  file
my_command: /path to/genericfile
my_command: /path/to/regular.file
my_command: /path/to/exciting!/file!
my_command: /path/to/(parenthetical)/file.txt
my_command: /books/Hitchhiker's Guide to the Galaxy.epub

或者在 ksh93 中(向吉尔斯的回答在这里用于手动实现 readarray):

$ IFS=$'\n'; set -f
$ paths=( $(< baard.in) )
$ unset IFS; set +f
$ for((i=0;i < ${#paths[*]}; i++)) do ./my_command "${paths[i]}"; done
my_command: /path/to/some space file
my_command: /some       tabbed/some     tabbed  file
my_command: /path to/genericfile
my_command: /path/to/regular.file
my_command: /path/to/exciting!/file!
my_command: /path/to/(parenthetical)/file.txt
my_command: /books/Hitchhiker's Guide to the Galaxy.epub

相关内容