2

I have found many answers to sort the files of directory and even to save them in an array.

Sorting Example

ls -t 

Directory listing in array

array=(*)

My particular problem needs to sort files with a specific extension (say *.sh) based on their modification date/time, and save all these sorted files in array to be used later for editing or deleting file.

For example, after I have the sorted files in the array I could execute remove the most recent file by the following command.

rm ${array[0]} 
  • @Osaid- array=($(ls -t *.sh)) is quick and dirty though it will not handle file names with spaces in them. – fd0 Jul 6 '15 at 13:22
1

In zsh it's as easy as

array=(*.sh(Nom))

The glob qualifier om causes the matches to be sorted by modification time (newest first), and N forces the array to be empty if there is no match (instead of causing an error).

In other shells such as bash, there's no good way of sorting by time. You can use ls -t, but that can break because the output is ambiguous. If you know that your file names only contain characters that ls considers to be printable, and that are not whitespace or \[*?, then you can use a command substitution:

array=($(ls -t -- *.sh 2>/dev/null))

You can make this more robust by protecting wildcard characters and horizontal whitespace, but newlines and nonprintable characters remain a problem.

IFS=$'\n'; set -f
array=($(ls -t -- *.sh 2>/dev/null))
unset IFS; set +f

Except in zsh, don't forget the double quotes when refering to the value of a variable, as well as -- to protect files whose name begins with a dash and would otherwise be interpreted as options, e.g. rm -- "${array[0]}"

1

To do this with ls robustly you should not split on anything but the path delimiter - that's what it's for.

IFS=/; set -f
set -- $(ls -dt ./*)
shift

That will sort all non-dot files in the current directory and place the results in the shell array $@. Given a POSIX ls, this is not susceptible to any kind of filename mangling whatsoever: special characters of all kinds - including newlines - persist in the delimited results. Each one (but the last), though, will have an extra . dot appended to the name. If you wanted to put the results in a more permanent array, you could handle the jobs together, like:

a=()
until [ -z "$2" ] &&
      a+="$1" && shift
do    a+="${1%?}"
shift;done

No matter what kind of nonsense blogs some others might link you to, you can handle ls's results robustly if you just know what to look for.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.