matandked
matandked

Reputation: 1565

Bash - recursively search files from the list and copy them to destination

I have a list of file names (without full path, only file names containing extensions) which I would like to find in subfolders of specified path (dir) and copy them to destination (dest) folder. Each file name is separated by the newline character.

I'm not aware of any tool to do that (i.e. I can't find appropriate option in Gnome Commander), so I wrote a small Bash script for that:

#!/bin/bash

dir="~/Dropbox/in_THIS_folder_and_subfolders_of_this_folder_I_have_files_which_I_wish_to_copy"
dest="~/PleaseCopyMeHere"
listOfFileNamesToCopy="ext-SM_OPER_MIR_CLF33A_20160303T000000_20160305T235959_300_002_7_1.DBL.nc.png
ext-SM_OPER_MIR_CLF33A_20160306T000000_20160308T235959_300_003_7_1.DBL.nc.png
DA_TC_MIR_CL_33SMOS_20160305.DBL.nc_hist_pl.pdf
msk_TC_cal_sub_msk_TC_ca__sum__SMOS_20160303.DBL_div_filt.tif.png
summsk_TC_cal_sub_msk_TC_ca__sum__SMOS_20160303.DBL_div_filt.tif_hist_pl.pdf
"

while read line; do
   find "$dir" -name "$line" -exec cp '{}' $dest    
done < "$listOfFileNamesToCopy"

Unfortunately it's not working and I have no idea what is wrong. Could you suggest solution, please?

Upvotes: 1

Views: 136

Answers (1)

Inian
Inian

Reputation: 85620

Your idea is right, but the input to the loop is provided in an incorrect way. The syntax you adopted is for reading contents of a file. But to expand a variable use a here-string syntax(<<<"$variable") which expands the variable and sends it as the input to the loop.

Since the values in variables are separated by \n entries, you need to de-limit by that character while setting input field separator, IFS while running the loop i.e. (or) using the de-limiter flag provided by read command with -d$'\n' which is by default the operation of read. Also remove he ~ in double-quotes and use $HOME for expansion as @gniourf_gniourf suggested in the comments.

dir="$HOME/Dropbox/in_THIS_folder_and_subfolders_of_this_folder_I_have_files_which_I_wish_to_copy"
dest="$HOME/PleaseCopyMeHere"

while IFS=$'\n' read -r line
do
    find "$dir" -name "$line" -exec cp '{}' "$dest" \;
done <<<"$listOfFileNamesToCopy"

should solve your problem.

As a side note, when unsure of the new-line separation in variable values, use hexdump -c to see it for yourself. In your case, I did, hex byte level representation of the data enabled by the -c flag and see the \n characters after each file-name.

dudeOnMac:myScripts $ echo "$listOfFileNamesToCopy" | hexdump -c
0000000   e   x   t   -   S   M   _   O   P   E   R   _   M   I   R   _
0000010   C   L   F   3   3   A   _   2   0   1   6   0   3   0   3   T
0000020   0   0   0   0   0   0   _   2   0   1   6   0   3   0   5   T
0000030   2   3   5   9   5   9   _   3   0   0   _   0   0   2   _   7
0000040   _   1   .   D   B   L   .   n   c   .   p   n   g  \n   e   x
0000050   t   -   S   M   _   O   P   E   R   _   M   I   R   _   C   L
0000060   F   3   3   A   _   2   0   1   6   0   3   0   6   T   0   0
0000070   0   0   0   0   _   2   0   1   6   0   3   0   8   T   2   3
0000080   5   9   5   9   _   3   0   0   _   0   0   3   _   7   _   1
0000090   .   D   B   L   .   n   c   .   p   n   g  \n   D   A   _   T
00000a0   C   _   M   I   R   _   C   L   _   3   3   S   M   O   S   _
00000b0   2   0   1   6   0   3   0   5   .   D   B   L   .   n   c   _
00000c0   h   i   s   t   _   p   l   .   p   d   f  \n   m   s   k   _
00000d0   T   C   _   c   a   l   _   s   u   b   _   m   s   k   _   T
00000e0   C   _   c   a   _   _   s   u   m   _   _   S   M   O   S   _
00000f0   2   0   1   6   0   3   0   3   .   D   B   L   _   d   i   v
0000100   _   f   i   l   t   .   t   i   f   .   p   n   g  \n   s   u
0000110   m   m   s   k   _   T   C   _   c   a   l   _   s   u   b   _
0000120   m   s   k   _   T   C   _   c   a   _   _   s   u   m   _   _
0000130   S   M   O   S   _   2   0   1   6   0   3   0   3   .   D   B
0000140   L   _   d   i   v   _   f   i   l   t   .   t   i   f   _   h
0000150   i   s   t   _   p   l   .   p   d   f  \n  \n                
000015c

Upvotes: 1

Related Questions