4

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?

  • Did you mean to say (for internal consistency) that you expect foo to be listed fit? – Jeff Schaller Aug 30 '18 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 '18 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 '18 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. – Ondra Žižka Sep 3 '18 at 19:33
8

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
  • I should suggest you to complete your answer based on his own command. – Hamid Yousefi Sep 3 '18 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. – Ondra Žižka Jan 22 '19 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

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

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.