A pipe (|
) connects a process's standard output stream to another process's standard input stream. You can't use that to pass a list of filenames to rm
directly, because rm
does not read filenames from its standard input.
You could use the xargs
program to read the list on its standard input, and "bundle" the filenames for rm
:
ls -A | grep abcdef | xargs rm
but don't, there are all kinds of problems with this approach - in particular that grep
processes input line-by-line, while xargs
splits inputs on whitespace by default. You could make it better using something like
shopt -s dotglob # simulate ls -A "almost all" hidden files
printf '%s\0' * | grep -z abcdef | xargs -0 rm
which uses the ASCII null character to separate filenames unambiguously. A usually preferred approach is to use the find
command:
find . -maxdepth 1 -name '*abcdef*' # -delete
(I've left the -delete
commented for now - make absolutely sure it is find
ing the right files before uncommenting it, since there's no "undo" operation).
Note that find
recurses into subdirectories by default - if you want the equivalent of ls -R
then remove the -maxdepth 1
. You can add -type f
to find and delete files only (omitting directories).
Also note that find -name
uses shell glob patterns rather than the regular expressions used by grep
(it also has a -regex
match predicate but that doesn't seem to be necessary here).
See also Why not parse ls
(and what to do instead)?