Bash:ls的子shell行为

时间:2017-10-26 13:17:35

标签: bash shell scripting ls subshell

我想知道为什么我没有得到相同的输出:

ls -1 -tF | head -n 1

echo $(ls -1 -tF | head -n 1)

我试图获取最后修改过的文件,但是在子shell中使用它有时会得到多个文件?

为什么这样以及如何避免?

2 个答案:

答案 0 :(得分:6)

问题出现是因为你使用了一个不带引号的子shell和-F标志,用于ls输出附加到文件名的shell特殊字符。

  

-F, - 分类
              将指标(* / => @ |之一)附加到条目

可执行文件附加*。

运行时

echo $(ls -1 -tF | head -n 1)

然后

$(ls -1 -tF | head -n 1)

将返回一个文件名,如果它恰好是一个可执行文件并且也是另一个文件的前缀,那么它将返回两者。

例如,如果你有

test.sh
test.sh.backup

然后它会返回

test.sh*

当回声扩展到

test.sh test.sh.backup

引用子shell可防止此扩展

echo "$(ls -1 -tF | head -n 1)"

返回

test.sh*

答案 1 :(得分:0)

我刚发现错误: 如果您使用echo $(ls -1 -tF | head -n 1) 文件全球机制可能导致额外的匹配。

所以echo "$(ls -1 -tF | head -n 1)"会避免这种情况。

因为如果结果是可执行文件,那么它最后会包含*。

我尝试将 why -F 放在评论中,但现在我决定把它放在这里:

我在.bashrc中添加了以下行,以获得列出上次修改过的文件或目录的快捷方式:

function L {
  myvar=$1; h=${myvar:="1"};
  echo "last ${h} modified file(s):"; 
  export L=$(ls -1 -tF|fgrep -v / |head -n ${h}| sed 's/\(\*\|=\|@\)$//g' );    
  ls -l $L;
}
function LD {
  myvar=$1;
  h=${myvar:="1"};
  echo "last ${h} modified directories:"; 
  export LD=$(ls -1 -tF|fgrep / |head -n $h | sed 's/\(\*\|=\|@\)$//g'); ls -ld $LD;
}
alias ol='L; xdg-open $L'
alias cdl='LD; cd $LD'

所以现在我可以使用L(或L 5)列出最后(最后5个)修改过的文件。但不是目录。

和L; jmacs $ L我可以打开我的编辑器来编辑它。传统上我使用别名lt ='ls -lrt',但我必须重新输入名称...

现在在mkdir之后...我使用cdl更改为该目录。