使用文件中的glob读取参数列表

时间:2017-04-13 20:42:40

标签: bash unix xargs glob

我正在尝试从文件中读取ll命令的参数。 我的文件args.txt包含内容some?。我的文件名为some1some2some3以及其他一些文件。当我执行cat args.txt | ll时,我得到与执行ll时相同的结果。

有人可以解释我为什么会这样,我怎样才能达到预期的效果。 提前谢谢。

3 个答案:

答案 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