ksh storing result of a command to a variable

2020-03-24 04:07发布

I want to store the result of a command to a variable in my shell script. I cant seem to get it to work. I want the most recently dated file in the directory.

PRODUCT= 'ls -t /some/dir/file* | head -1 | xargs -n1 basename'

it wont work

5条回答
beautiful°
2楼-- · 2020-03-24 04:34

The problem that you're having is that the command needs to be surrounded by back-ticks rather than single quotes. This is known as 'Command Substitution'.

Bash allows you to use $() for command substitution, but this is not available in all shells. I don't know if it's available in KSH; if it is, it's probably not available in all versions.

If the $() syntax is available in your version of ksh, you should definitely use it; it's easier to read (back ticks are too easy to confuse with single quotes); back-ticks are also hard to nest.

This only addresses one of the problems with your command, however: ls returns directories as well as files, so if the most recent thing modified in the specified directory is a sub-directory, that is what you will see.

If you only want to see files, I suggest using some version of the following (I'm using Bash, which supports default variables, you'll probably have to play around with the syntax of $1)

lastfile () 
{ 
    find ${1:-.} -maxdepth 1 -type f -printf "%T+ %p\n" | sort -n | tail -1 | sed 's/[^[:space:]]\+ //'
}

This runs find on the directory, and only pulls files from that directory. It formats all of the files like this:

2012-08-29+16:21:40.0000000000 ./.sqlite_history
2013-01-14+08:52:14.0000000000 ./.davmail.properties
2012-04-04+16:16:40.0000000000 ./.DS_Store
2010-04-21+15:49:00.0000000000 ./.joe_state
2008-09-05+17:15:28.0000000000 ./.hplip.conf
2012-01-31+13:12:28.0000000000 ./.oneclick

sorts the list, takes the last line, and chops off everything before the first space.

查看更多
相关推荐>>
3楼-- · 2020-03-24 04:46

you have two options, either $ or backsticks`.

1) x=$(ls -t /some/dir/file* | head -1 | xargs -n1 basename)

or

2) x=`ls -t /some/dir/file* | head -1 | xargs -n1 basename`

echo $x

Edit: removing unnecessary bracket for (2).

查看更多
劫难
4楼-- · 2020-03-24 04:47

You need both quotes to ensure you keep the name even if it contains spaces, and also in case you later want more than 1 file, and "$(..)" to run commands in background

I believe you also need the '-1' option to ls, otherwise you could have several names per lines (you only keep 1 line, but it could be several files)

PRODUCT="$(ls -1t /some/dir/file* | head -1 | xargs -n1 basename)"

Please do not put space around the "=" variable assignments (as I saw on other solutions here) , as it's not very compatible as well.

查看更多
Anthone
5楼-- · 2020-03-24 04:48

I would do something like:

Your version corrected:

PRODUCT=$(ls -t /some/dir/file* | head -1 | xargs -n1 basename)

Or simpler:

PRODUCT=$(cd /some/dir && ls -1t file* | head -1)
  • change to the directory
  • list one filename per line and sort by time/date
  • grab the first line
查看更多
劫难
6楼-- · 2020-03-24 04:56

You want $() (preferred) or backticks (``) (older style), rather than single quotes:

PRODUCT=$(ls -t /some/dir/file* | head -1 | xargs -n1 basename)

or

PRODUCT=`ls -t /some/dir/file* | head -1 | xargs -n1 basename`
查看更多
登录 后发表回答