如果成功,则通过管道传输命令的输出

Gov*_*las 18 shell pipe output

INPUT_FILE=`ls -rt $MY_DIR/FILE.*.xml | head -1 | xargs basename`
Run Code Online (Sandbox Code Playgroud)

我只想head -1在第一个命令成功时执行第二个命令 ( )。如何改进此命令?

小智 13

尝试这个:

INPUT_FILE=`ls -rt "$MY_DIR"/FILE.*.xml | head -1 | xargs -r basename`
Run Code Online (Sandbox Code Playgroud)

传递xargs-r标志将使其仅basename在从标准输入 ( head -1) 中读取至少一项时才运行。

head -1 将运行,但您不会看到或捕获它的任何输出。

此外,如果您不希望用户看到来自 的任何错误输出ls,您可以将ls的 stderr 流重定向到/dev/null

INPUT_FILE=`ls -rt "$MY_DIR"/FILE.*.xml 2> /dev/null | head -1 | xargs -r basename`
Run Code Online (Sandbox Code Playgroud)

另请注意,我在$MY_DIR. 这样,如果$MY_DIR包含空格,该命令将不会失败。

如果您使用的是现代 shell,例如 bash,则应该使用$( )捕获 shell 而不是反引号。您还应该考虑更改变量的样式。您通常应该避免在脚本中使用全大写的变量名。该样式通常保留用于保留变量和环境变量。

input_file=$(ls -rt "$my_dir"/FILE.*.xml 2> /dev/null | head -1 | xargs -r basename)
Run Code Online (Sandbox Code Playgroud)


Sté*_*las 9

在管道中,所有命令都是同时启动和运行的,而不是一个接一个。所以你需要将输出存储在某个地方。

if ls_output=$(ls -rtd -- "$MY_DIR"/FILE.*.xml); then
  first_file=$(printf '%s\n' "$ls_output" | head -n 1)
  first_file_name=$(basename -- "$first_file")
fi
Run Code Online (Sandbox Code Playgroud)

请注意,它假定文件名不包含换行符。使用xargs也意味着空白字符、单引号和双引号以及反斜杠的问题。不加引号的变量意味着空格、制表符和通配符出现问题。忘记--意味着文件名以-.

要在zsh没有任何字符限制的情况下获取最旧文件的基本名称(也避免了命令参数大小受限的问题):

 first_file_name=($MY_DIR/FILE.*.xml(Om[1]:t))
Run Code Online (Sandbox Code Playgroud)

如果没有匹配项,该命令将失败并中止脚本。你也可以这样做:

 first_file_name=($MY_DIR/FILE.*.xml(NOm[1]:t))
Run Code Online (Sandbox Code Playgroud)

在这种情况下,first_file_name如果匹配,则数组将包含 1 个元素,否则为 0。然后你可以这样做:

 if (($#first_file_name)); then
    printf 'Match: %s\n' $first_file_name
 else
    echo >&2 No match
 fi
Run Code Online (Sandbox Code Playgroud)