Super User is a question and answer site for computer enthusiasts and power users. It's 100% free, no registration required.

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

Task: Create script, that will take 2 arguments: <directory> <destination>

Search the files in <directory> for substring “moveme” in the file content Move those files that contain the string to directory <destination>

My Bash:


if [ "$1" == "" ]; then
    echo "Retry..."
    if [ "$2" == "" ]; then
        echo "Retry ..."
        echo "Try to fiend in folder {$1} files with this content {123} "
        grep -l "123" $1/*
        #grep -c "123" $1/*

Question: How to transfer finded file from one directory to other?

share|improve this question
mv $directory/$file $destination/$file ? – NickW Jan 23 '14 at 11:54
Yes, of course, but which concretely file? – HerrGrau Jan 23 '14 at 11:55
$file -> how to write in this variable gotten resoult from grep – HerrGrau Jan 23 '14 at 11:57
You're probably going to want to use a while loop set a variable that contains the grep, while it exists, and if it is a file, move it to the new directory.. – NickW Jan 23 '14 at 12:00
yea, on theory i understand how to make it, but in practic? .. :( – HerrGrau Jan 23 '14 at 12:02

grep will return a list of files. You need to execute mv over each of the files.

You can use xargs as suggested in another answer, but I prefer this on-liner:

for file in $(grep -l "123" $1/*); do mv $file $2; done

It iterates over the list of files returned by grep and moves them one by one.

You may need to add some error checking, so here is a more readable version:

for file in $(grep -l "123" $1/*); do
    mv $file $2;

Also, I find it's usually a good idea to change the IFS variable before this kind of loop

export IFS=$'\n'

That way, you will avoid a lot of problems with files having whitespace in the name (unless they have a newline character embedded).

share|improve this answer
Note that for <n> files and <m> matching files, the xargs method calls grep <n> times and mv <m> times. The for loop calls grep only once. – GnP Jan 23 '14 at 19:11
Changing the IFS isn't encouraged just to fix a command that breaks on whitespace. If you want to iterate over files, it's better to use find and its -exec capabilities. Also, you should double-quote your variables. – slhck Jan 25 '14 at 18:53
find "$1"/* -prune -type f -exec grep -l "$str" "{}" \; | xargs -i echo mv -i "{}" "$2"/

Actually, to check no. of arguments, checking $2 is enough

if [ "$2" == "" ]; then
        echo "Retry ..."

More importantly, you should handle the possible overwrites to the files in $2.

share|improve this answer
When piping from find to xargs, use find … -print0 | xargs -0 – slhck Jan 25 '14 at 18:51
Thanks. Just learned how to avoid the possible \n in a filename from your comment. – chingNotCHing Jan 27 '14 at 14:23

if [ "$1" == "" ]; then
    echo "Retry... ./ {folder_from}/ {text} {folder_to}/"
    if [ "$2" == "" ]; then
        echo "Retry ... ./ {folder_from}/ {text} {folder_to}/"
        echo "Try to find in folder {$1} files with this content {123} "
        cd ~/tasks/$1
        grep -l "123" * > list.txt
        while read line
            mv $line  ~/tasks/$3/$line
        done < list.txt
        #grep -c "123" $1\/*
        rm list.txt
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.