Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Filter list of files to those that exist

Tags:

file

bash

How do I filter a list of files to the ones that exist?

For example,

echo 'a.txt
does/not.exist
b.txt' | <???>

would print

a.txt
b.txt 
like image 241
Paul Draper Avatar asked Jan 14 '14 16:01

Paul Draper


3 Answers

You can ls -d the files and see which ones get some output. Since you have those in a string, just pipe the list and use xargs to be able to ls them.

To hide errors, redirect those to /dev/null. All together, xargs ls -d 2>/dev/null makes it:

$ echo 'a.txt
b.txt
other' | xargs ls -d 2>/dev/null
a.txt
b.txt

As you see, xargs ls -d executes ls -d to all the arguments given. 2>/dev/null gets rid of the stderr messages.

like image 192
fedorqui 'SO stop harming' Avatar answered Nov 07 '22 12:11

fedorqui 'SO stop harming'


If you have GNU xargs, use -d '\n' to ensure that filenames (including directories) with embedded spaces are handled correctly, by splitting the input into whole lines rather than also by intra-line whitespace.

echo 'a.txt
does/not.exist
b.txt' | xargs -d '\n' ls -1df 2>/dev/null

Note:

  • The ls command emits an error for each non-existent input path, which 2>/dev/null ignores, while echoing existing paths as-is.

  • Option -1 prints each path on its own line, -d prevents recursing into directories, and -f prevents sorting of the input paths (if you actually want sorting, omit the f).


On macOS/BSD, xargs doesn't support -d, which requires a workaround via NUL-separated input using tr and xargs's -0 option:

echo 'a.txt
does/not.exist
b.txt' | tr '\n' '\0' | xargs -0 ls -1df 2>/dev/null
like image 29
mklement0 Avatar answered Nov 07 '22 12:11

mklement0


As a one-liner, and pure bash for speed (improved from mklement0's answer, would have commented if I'd had the rep):

{ ls; echo does/not.exist; } | while IFS= read -r f; do [[ -f "$f" ]] && echo "$f"; done
like image 5
Tommy Jollyboat Avatar answered Nov 07 '22 11:11

Tommy Jollyboat