Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I need to select files which contain "Error" or "traffic" in their names, e.g.


and move them into corresponding directories like Error_directory and traffic_directory according to their names.

I tried this but it didnt work

mv $(ls test_file | grep -l 'Error>' *) Error_directory

How can I do this with a bash command?

ls test_file | grep 'Error'
share|improve this question
grep is irrelevant here. Start with the task, and then determine the tools, and try to avoid using Unix commands as verbs unless that is exactly what you mean. – jw013 Sep 14 '12 at 18:48

Parsing the output of ls is rarely a good idea due to the wide range of characters that can occur in file names. A better solution might be:

find ./test_file -iname "*error*" -print0 | xargs -0 -I {} mv {} Error_directory

Notice the -iname option. This will return case insensitive matches, allowing you to find and move files such as:


If you don't need your search to be case insensitive, something as simple as this should suffice:

mv test_file/*Error* Error_directory

Further reading:

xargs separator problem

bash pitfalls

share|improve this answer
+1 for pointing out the error in attempting to use ls, but piping find directly to xargs isn't any safer. Use find -print0 | xargs -0 OR find ... -exec instead. Shell globs are usually the best way to go, if possible. – jw013 Sep 14 '12 at 18:54
@jw013: Thanks, good spot. I added some resources for anyone interested in avoiding these problems. – tojrobinson Sep 14 '12 at 19:28

Another possible solution is:



for f in *.csv; do
    case $f in
        *[Ee][Rr][Rr][Oo][Rr]*) mv -i $f $err_dir ;;
        *[Tt][Rr][Aa][Ff][Ii][Cc]*) mv -i $f $tra_dir ;;
share|improve this answer
You could get away with just sh since no bash-specific features were used or required in this snippet. Also, for future reference, case doesn't do word splitting so you don't need the double quotes around $f. – jw013 Sep 14 '12 at 18:55
@jw013 Thanks for the reminder. Is there a way to use regular expression instead of globs in case statements? – user13742 Sep 14 '12 at 19:00
POSIX sh doesn't do regex in case or anywhere else that I know of, and bash doesn't in case AFAIK. Usually globs are sufficient but if you require regex you might have to go with a fancier shell or find. In this particular case regular expressions are overkill. – jw013 Sep 14 '12 at 19:03

You could use find:

find test_file -type f -name "*Error*" -exec mv {} Error_directory/ \;

where -type f denotes that you are looking for files, -name states that you are matching on the pattern given. exec runs the following command, with the {} taking the place of files that match the parameters given to find.

If you want to use bash and do something more along the lines of what you've tried, a loop should do the trick:

for f in `ls test_file | grep 'Error'; do
  mv test_file/${f} Error_directory

In both examples, I've assumed test_file is a directory containing the files you are interested in.

share|improve this answer
for fn in *.*; do for word in Error traffic; do echo "$fn" | grep -i "$word" && mkdir -p "$word"_directory && mv "$fn" "$word"_directory; done; done
share|improve this answer
ls | grep Error | xargs -I % mv % error-dir
share|improve this answer

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

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