I have many files in a SRC folder. I would like to move all the files that follow a particular pattern from this SRC folder to another DST folder along with rename the file with a required extension.

Sample Parameters

SRC directory /Vinodh

Files in /Vinodh folder are TEST01, TEST02, TEST03, TEST04

TEST02 & TEST03 contain the word WORLD

DST directory /TEST

I want to move the TEST02 & TEST03 files to /TEST folder as TEST02.txt and TEST03.txt

I will be typing the command as

cd /Vinodh
grep -l 'WORLD' *TEST*
cd /TEST
mv TEST02 TEST02.txt
mv TEST03 TEST03.txt

I'd like to combine all this to a single line statement or have batch file that copies all the files in a single shot.


With GNU tools:

grep -D skip -d skip -lZ WORD /Vinodh/*TEST* | xargs -r0 mv -vt /TEST

Note that if some of those files are symlinks, moving them could break links.

GNU grep can skip devices/fifos with -D skip, and directories with -d skip, but there's no option to skip symlinks. You'd need a shell where globs can specify file types like zsh:

grep -lZ WORD /Vinodh/*TEST*(.) | xargs -r0 mv -vt /TEST

Would only look in regular files.

An alternative is to use find:

LC_ALL=C find /Vinodh/. ! -name . -prune \
  ! -name '.*' -type f -name '*TEST*' -exec grep -lZ WORD {} + |
  xargs -r0 mv -t /TEST

And the POSIX variant if you don't have GNU tools:

LC_ALL=C find /Vinodh/. ! -name . -prune \
  ! -name '.*' -type f -name '*TEST*' -exec grep -q {} \; \
  -exec mv {} /TEST/ \;
  • Neither of your examples rename file from TEST0X to TEST0X.txt – NarūnasK Dec 13 '17 at 13:19

Loop over the files with for f..., then wrap the mv inside a conditional (see e.g. TestsAndConditionals on BashGuide):

cd /Vinodh
for f in *TEST* ; do
    if grep -q WORLD "$f" ; then
        mv "$f" "/TEST/$f.txt"

Assuming your shell is Bash:

for file in "$source_directory/"*; do
  renamed_file="$(basename "$file")"
  if grep -q 'WORLD' "$file"; then
    echo "Moving \"$file\" to \"$destination_directory/${renamed_file%.*}.txt\""
    mv "$file" "$destination_directory/${renamed_file%.*}.txt"
  1. Iterate over all files in $source_directory.
  2. Extract the file name (the part after the last /).
  3. Look for the string WORLD in the file; grep -q is quiet, that is, it just sets the exit code and does not print what it did.
  4. If the string is found in the file, then move it to $destination_directory replacing any suffix with .txt.

Here's one liner for you:

cd /Vinodh && for x in $(grep -sl 'WORLD' *TEST*); do mv "$x" "/TEST/$x.txt"; done
grep -li "world" /Vinodh/* | awk '{print "mv" " " $1 " " "/TEST/"}' | sh

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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