6

I have a specific order of files that I want to list if they exist; around 40 files. Some kind of precedence. So I tried:

ls -1d         /opt/foo/lib.jar /opt/bar/lib.jar

I expected this to list /opt/foo/lib.jar first if both exist. But actually it prints the bar first and the foo after that.

Is there some way to make ls list the entries in the order given in parameters?
Or some alternative approach with find?

4
  • Did you mean to say (for internal consistency) that you expect foo to be listed fit?
    – Jeff Schaller
    Aug 30, 2018 at 23:47
  • How would you describe the rule for sorting these 40 files? Completely manually based on the command line?
    – Jeff Schaller
    Aug 30, 2018 at 23:48
  • This question has been negatived from someone, I don't think this was fair. This is a legitimate question and, indeed, Mathew's answer seems to address it correctly.
    – Marcelo
    Aug 31, 2018 at 1:38
  • @JeffSchaller Yes, on a command line. It's a script that's identifying what's "installed". I admit there could be a smater way (a list in a file) but the way to get the script and files to the machine is complicated, so this works best. Sep 3, 2018 at 19:33

5 Answers 5

14

With GNU ls, you could try the -U option:

-U: do not sort; list entries in directory order

(though here, we're not listing the content of directories, so the part that matters is do not sort).

$ ls -1dU /opt/foo/lib.jar /opt/bar/lib.jar
/opt/foo/lib.jar
/opt/bar/lib.jar

Slightly more portable (works with GNU and FreeBSD ls, but not with traditional ls implementations and is not POSIX either), you can use ls -1df:

$ ls -1df /opt/foo/lib.jar /opt/bar/lib.jar
/opt/foo/lib.jar
/opt/bar/lib.jar
2
  • I should suggest you to complete your answer based on his own command. Sep 3, 2018 at 19:39
  • Mac's ls does not support -U. So, while this is better for Linux, for a general case I opted for find as I need this to work on MacOS, too. Jan 22, 2019 at 10:01
1

After mentioning find, I found out that it can take more than 1 path as the path argument. So it is simply:

 find /opt/foo/lib.jar /opt/bar/lib.jar -prune 2> /dev/null
1
  • This is a good answer, but not the correct answer to the question. See @Matthew answer below.
    – 4wk_
    Feb 16, 2022 at 15:29
1

You could create a wrapper function around ls that loops over the arguments (in the order they're given), calling ls on each:

myls() {
  for arg do
    ls -d -- "$arg"
  done
}

With a reference to Stéphane's answer in How to use arguments like $1 $2 ... in a for loop? for the for arg do syntax.

0

In zsh, to reduce a list of files to the ones that exist, you can use the (N) glob qualifier appended to each element of the list:

files=(/opt/foo/lib.jar /opt/bar/lib.jar)
that_exist=($^files(N))

(($#that_exist > 0 )) && print -rl -- $that_exist

Note that contrary to ls, it can tell whether a file exists or not even if you don't have search access to its parent directory (as long as you still have read access), as it looks for corresponding entries in the directory without trying to access the file.

See also:

that_exist_after_symlink_resolution=($^files(N-^@))

Which selects the files that are not (^) a symlink (@) after symlink resolution (-). Equivalent to using ls -Ld.

0

If you have a list of pathnames that you'd like to go through and test for existence, then I presume that you'd like to either do something fol the ones that do exist, for the ones that don't exist, or for both sets of pathnames.

Given a standard shell, this is best done in a loop.

for pathname in /the/first/path /the/second/path /some/other/path
do
    if [ -e "$pathname" ]; then
        printf 'Path "%s" exists\n' "$pathname"
    else
        printf 'Path "%s" does not exist\n' "$pathname"
    fi
done

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .