Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

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

abc_ERRor.csv
raError.csv
bsn_Error.csv
bbbctraffic.csv
ccc_traffic.csv
...

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

5 Answers 5

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:

abc_ERRor.csv
error_123.csv
ErRoR_77.csv

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  
+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
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

Another possible solution is:

#!/bin/sh

err_dir=~/errors
tra_dir=~/traffic

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 ;;
    esac
done
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? –  Herman Torjussen Sep 14 '12 at 19:00
1  
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
ls | grep Error | xargs -I % mv % error-dir
share|improve this answer

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
done

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

share|improve this answer

Your Answer

 
discard

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.