简体   繁体   中英

Bash: Subshell behaviour of ls

I am wondering why I do not get se same output from:

ls -1 -tF | head -n 1

and

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

I tried to get the last modified file, but using it inside a sub shell sometimes I get more than one file as result?

Why that and how to avoid?

The problem arises because you are using an unquoted subshell and -F flag for ls outputs shell special characters appended to filenames.

-F, --classify
append indicator (one of */=>@|) to entries

Executable files are appended with *.

When you run

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

then

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

will return a filename, and if it happens to be an executable and also be the prefix to another file, then it will return both.

For example if you have

test.sh
test.sh.backup

then it will return

test.sh*

which when echoed expands to

test.sh test.sh.backup

Quoting the subshell prevents this expansion

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

returns

test.sh*

I just found the error: If you use echo $(ls -1 -tF | head -n 1) the file globing mechanism may result in additional matches.

So echo "$(ls -1 -tF | head -n 1)" would avoid this.

Because if the result is an executable it contains a * at the end.

I tried to place the why -F in a comment, but now I decided to put it here:

I added the following lines to my .bashrc, to have a shortcut to get last modified files or directories listed:

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'

So now I can use L (or L 5) to list the last (last 5) modified files. But not directories.

And with L; jmacs $LI can open my editor, to edit it. Traditionally I used my alias lt='ls -lrt' but than I have to retype the name...

Now after mkdir ... I use cdl to change to that dir.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM