我正在尝试从文件中读取ll
命令的参数。
我的文件args.txt
包含内容some?
。我的文件名为some1
,some2
和some3
以及其他一些文件。当我执行cat args.txt | ll
时,我得到与执行ll
时相同的结果。
有人可以解释我为什么会这样,我怎样才能达到预期的效果。 提前谢谢。
答案 0 :(得分:5)
注意:我假设> d2
X1 X2
1 Northampton Stop and Shop
2 Northampton Stop and Shop
3 Northampton Whole Foods
4 Amherst Whole Foods
5 Amherst Whole Foods
6 Amherst Whole Foods
7 Amherst Whole Foods
8 Amherst Whole Foods
9 Hadley Stop and Shop
10 Hadley Stop and Shop
是ll
的别名或某些变体。
正如Charles Duffy指出的那样,(默认情况下)只有交互式shell 知道别名,脚本以及ls -l
之类的工具都不知道它们。
通过管道向命令发送的内容通过其 stdin 流接收,该流与命令的参数不同({{em>等选项) 1}}和操作数,例如xargs
)。
因此,需要显式转换才能将文件-l
的内容转换为参数 ,您可以传递给some?
:
args.txt
请注意,命令替换(ls -l
)是故意不加引号,以确保将 globbing (文件名扩展)应用于{{的内容1}},根据需要。
你的情况很少见,这种技术 - 脆弱 - 实际上是需要。
为了说明脆弱性:例如,如果你的globbing模式是ls -l $(cat args.txt) # In Bash you can simplify to: ls -l $(< args.txt)
(你需要将模式的双引号仍然被识别为单个参数),那么命令就不会出现这种情况。因为当$(...)
个字符是命令替换(或变量扩展)的结果时,args.txt
字符会失去语法功能。
用于将stdin或文件内容转换为参数的标准实用程序是"some file"?
。但是,在您的特定情况下不是选项,因为您的文件包含 glob (文件名模式),必须展开通过shell ,但"
仅调用外部实用程序,而不涉及shell:
xargs
文件名xargs
已经字面上传递给$ xargs ls -l < args.txt # !! Does NOT work as intended here.
ls: file?: No such file or directory
(并且实际上没有名为file?
的文件存在) - 没有发生全局,因为没有涉及shell。 / p>
答案 1 :(得分:3)
以下内容有点矫枉过正,但无论shell配置如何,都要努力做到正确和一致,并且要处理所有可能的文件名(即使是那些有空格的文件名):
# note f() ( ) instead of f() { }; this runs in a subshell, so its changes to IFS or
# shopt settings don't modify behavior of the larger shell.
globfiles() (
set +f ## ensure that globbing is enabled
shopt -u nullglob failglob ## ensure that non-default options on how to handle failed
## ...glob attempts are both disabled
IFS= ## disable string-splitting
while IFS= read -r -d '' filename; do
printf '%s\0' $filename ## unquoted use -> expand as glob
## ...expands format string once per argument, hence once per
## ...file found. (No string-splitting due to prior IFS=)
done
)
...之后用作(如果您的输入文件是换行符分隔的):
tr '\n' '\0' <args.txt | globfiles | xargs -0 ls -l --
...或(如果您的输入文件是NUL分隔的 - 这是理想的,因为这允许引用包含文字换行符的文件名):
globfiles <args.0sv | xargs -0 ls -l --
答案 2 :(得分:0)
您可以使用xargs
将cat的输出传递给命令(在您的情况下为ll
):
cat args.txt | xargs ll
如果你的args.txt包含多个值,用新行或空格分隔,xargs
将分别传递每个值,执行命令多次,作为args.txt中的条目:
例如,如果您的args.txt包含以下内容:
/var/
/usr/
/usr /var
然后执行结果如下:
$ cat args.txt | xargs ls
/usr:
bin etc games include lib lib64 libexec local sbin share src tmp
/usr/:
bin etc games include lib lib64 libexec local sbin share src tmp
/var:
adm cache crash cvs db empty games gopher kerberos lib local lock log mail nis opt preserve run spool tmp var yp
/var/:
adm cache crash cvs db empty games gopher kerberos lib local lock log mail nis opt preserve run spool tmp var yp