AshBrad
AshBrad

Reputation: 492

Pass a list of filenames from a .txt to a find and copy command

I have a .txt file with a list of xml file names. I need to take each xml file and pair it to an image of the same name somewhere else in my directory.

I already use sed to clean the .xml from the file name

Text File Example:
 DF_0001.jpg.xml
 DF_0002.jpg.xml

 After 'sed' cleaning:
 DF_0001.jpg
 DF_0002.jpg

 Source File and Path Example:
 path/to/drive/1/DF0001.jpg
 path/to/drive/2/DF0002.jpg

My .txt file containing the xml file list is here. This is where the actual xml files are as well:

 /Sites/csv/file_list.txt
 /Sites/csv/DF_0001.jpg.xml
 /Sites/csv/DF_0002.jpg.xml

My image files (by the same name) live in any number of directories here:

 /Images/JPG/Day1/DF_0001.jpg
 /Images/JPG/Day1/DF_0002.jpg
 /Images/JPG/Day1/DF_0003.jpg
 /Images/JPG/Day2/DF0004.jpg
 /Images/JPG/Day2/DF0005.jpg

Simply put: I need to find a .jpg file from a txt file, and move the corresponding xml to it.

Upvotes: 1

Views: 1763

Answers (2)

whoan
whoan

Reputation: 8531

sed 's/\.xml//' /Sites/csv/file_list.xml > /tmp/your_jpg_files.txt
find /Images/JPG -type f -name "*.jpg" | grep -F -f /tmp/your_jpg_files.txt |
while read FILEPATH; do
    mv "/Sites/csv/${FILEPATH##*/}.xml" "${FILEPATH%/*}"
done

Explanation:

sed 's/\.xml//' /Sites/csv/file_list.xml > /tmp/your_jpg_files.txt

Read the filenames from file_list.xml, remove the suffix .xml and save the result in a temp file.


find /Images/JPG -type f -name "*.jpg"

List all the paths to the .jpg files since the directory /Images/JPG


grep --fixed-strings --file=/tmp/your_jpg_files.txt

In the list of paths, you look the ones of your jpg files


while read FILEPATH; do
    mv "/Sites/csv/${FILEPATH##*/}.xml" "${FILEPATH%/*}"
done

At this step, you have all the paths to the .jpg files and for any of them, you'll make the mv you want.

${FILEPATH##*/} = $(basename "$FILEPATH") but more efficient.
${FILEPATH%/*} = $(dirname "$FILEPATH") but more efficient.


Example

FILEPATH contains /Images/JPG/Day2/DF0005.jpg, so the actual mv will be:

# /Sites/csv/${FILEPATH##*/}.xml -> /Sites/csv/DF0005.jpg.xml
# ${FILEPATH%/*} -> /Images/JPG/Day2/
mv "/Sites/csv/DF0005.jpg.xml" "/Images/JPG/Day2/"

Upvotes: 1

gboffi
gboffi

Reputation: 25092

The following is based on the assumption that you have no spaces neither in filenames nor in pathnames and that the xml file names are stored in a file named "xmls" (treating spaces in path/file names is probably simple but for sure it's tedious).

find . -type f -name '*.jpg' | while read a ; do 
    printf '%s ' `dirname "$a"`
    basename "$a"
done > jpegs
awk 'NR == FNR {tmp=$0;sub(".xml$","");xml[$0]=tmp;next}
    {if(xml[$2]) {print "cp ", xml[$2], $1 }}' xmls jpegs

The first command finds all the jpegs in the current and deeper directories, you can easily change that, and then feeds the pathnames to a pipeline that splits the path from the filename proper, the second one reads the "xmls" file to build an array of xml names indexed by the jpegs names and then processes the other file, printing a shell command if there is a match.

Upvotes: 1

Related Questions