Take the 2-minute tour ×
Super User is a question and answer site for computer enthusiasts and power users. It's 100% free, no registration required.

Task: Create script, that will take 2 arguments:

3.sh <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:

#!/bin/bash

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

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

share|improve this question
    
mv $directory/$file $destination/$file ? –  NickW Jan 23 at 11:54
    
Yes, of course, but which concretely file? –  HerrGrau Jan 23 at 11:55
    
$file -> how to write in this variable gotten resoult from grep –  HerrGrau Jan 23 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 at 12:00
    
yea, on theory i understand how to make it, but in practic? .. :( –  HerrGrau Jan 23 at 12:02

3 Answers 3

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;
done

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 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 at 18:53
str="moveme"
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 at 18:51
    
Thanks. Just learned how to avoid the possible \n in a filename from your comment. –  chingNotCHing Jan 27 at 14:23
#!/bin/bash

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