This might be a very simple thing for a shell scripting programmer but am pretty new to it. I was trying to execute the below command in a shell script and save the output into a variable
inputfile=$(ls -ltr *.{PDF,pdf} | head -1 | awk '{print $9}')
The command works fine when I fire it from terminal but fails when executed through a shell script (sh). Why is that the command fails, does it mean that shell script doesn't support the command or am I doing it wrong? Also how do I know if a command will work in shell or not?
Just to give you a glimpse of my requirement, I was trying to get the oldest file from a particular directory (I also want to make sure upper case and lower case extensions are handled). Is there any other way to do this ?
Is
perl
an option? It's ubiquitous on Unix.I would suggest:
Which:
glob
to fetch all files matching the pattern.-M
which is relative modification time. (in days).[0]
) off the sort.Parsing
ls
is always a bad idea. You need another strategy.How about you make a function that gives you the oldest file among the ones given as argument? the following works in Bash (adapt to your needs):
Then just call as:
Now, you probably don't want to use brace expansions like this at all. In fact, you very likely want to use the shell options
nocaseglob
andnullglob
:If you're using a POSIX shell, it's going to be a bit trickier to have the equivalent of
nullglob
andnocaseglob
.As @gniourf_gniourf says, parsing ls is a bad idea. Such as leaving unquoted globs, and generally not counting for funny characters in file names.
find is your friend:
Notes:
find
has numerous ways of formatting the output, including things like access time and/or write time. I used'%T@ %p\n'
, where%T@
is last write time in UNIX time format incl.fractal part. This will never containt space so it's safe to use as separator.Numeric sort and tail get the last item, sorting by the time,
cut removes the time from the output.
I used IMO much easier to read/maintain pipe notation, with help of
\
.the code should run on any POSIX shell,
You could easily adjust the function to parametrize the pattern, time used (access/write), control the search depth or starting dir.
The above command will work correctly only if BOTH
*.pdf
and*.PDF
files are in the directory you are currently. If you would like to execute it in a directory with only one of those you should consider using e.g.:NOTE: The above command doesn't work with files with new lines, or with long list of found files.