copying files with a string in their name from one folder to another

I have some files in a directory as follows.

source_dir: 
ABCD.HRA.0014.2.200.png
ABCD.HRA.0015.2.200.png
ABCD.HRA.0016.2.200.png
MMNP.HRA.0016.2.200.png

I also have a text file with following content.

text.txt:

ABCD.HRA.0014
ABCD.HRA.0015

Now is there any way I can transfer the files as per the string mentioned in text.txt. After command, source dir and dest_dir should be as follows.

source_dir: 
ABCD.HRA.0016.2.200.png
MMNP.HRA.0016.2.200.png

dest_dir: 

ABCD.HRA.0014.2.200.png
ABCD.HRA.0015.2.200.png

Solution 1:

grep -f allows you to use text.txt as a source for patterns.

#!/bin/bash  
for i in source_dir/*.png; do  
  if grep -Fq -f text.txt <<< "$i"; then  
    mv -t dest_dir "$i"  
  fi  
done  
$ ls
dest_dir  script.sh  source_dir  text.txt

grep options:

  • -F Interpret patterns as fixed strings, not regular expressions.
  • -q Do not write anything to stdout.
  • -f Obtain patterns from FILE, one per line.

Here strings:

  • <<< A variant of here documents, does variable expansion before sending the string.

mv options:

  • -t Move all source arguments into -t directory.

Solution 2:

Your files all seem to end in .2.200.png, hence we can use the input file only:

while read line ; do
  mv "source_dir/${line}.2.200.png" destination_dir/
done < text.txt

Solution 3:

One way, if you know all the filenames in the file contain no whitespace, is like this:

cp $(cat text.txt) targetdir/

I always add the / at the end - this makes the command fail if targetdir doesn't exist and is a directory; you want that to happen, because otherwise you may end up copying all the files into one called targetdir (actually, I think that doesn't happen anymore in modern bash; I'm that old)

If each line in the file contains one filename, which may contain whitespace, the this method works, at least in ksh and newer versions of bash:

cat text.txt | while read l
do
cp "$l" targetdir/
done

And if that doesn't work in your version of bash, then this does (note the < text.txt after done):

while read l
do
cp "$l" targetdir/
done < text.txt