How to come in only in the new directory with script bash - bash

#!/bin/bash
#cicle 1
for fname in *.xlsx *csv
do
dname=${fname%.*}
[[ -d $dname ]] || mkdir "$dname"
mv "$fname" "$dname"
done
# In questo ciclo per ogni gene entra nella cartella e lancia i programmi di getChromosomicPositions.sh per avere
# le posizioni nel genoma, e getHapolotipeStings.sh per avere le varianti
#cicle 2
for geni in */; do
cd $geni
z=$(tail -n 1 *.csv | tr ';' "\n" | wc -l) # geuarda nel file csv quante colonne ci sono e trasferisce il riusltato al programma getChromosomicPositions
cd ..
cp getHGSVposHG19.sh $geni
cp getChromosomicPositions.sh $geni
cp getHaplotypeStrings.sh $geni
cd $geni
pippo=$(basename $(pwd))
export z
export pippo
./getChromosomicPositions.sh *.csv
export z
./getHaplotypeStrings.sh *.csv
cd ..
done
I have this script with 2 cicle,
I want that at the cicle 2 do the work of compilate the programs only for the new directory created in the cicle 1.
I mean:
I have the principal directory with this file:
pippo.xlsx pippo.csv
caio.xlsx caio.csv
topolino(directory)
minny(directory)
paperino(directory)
in the cicle 1 make the directorys pippo and caio
I want that at the cicle 2 I want that comes in in the new directory (pippo, caio) and makes all the work of cicle only to the new directory pippo and caio but not to the old directorys topolino, minny and paperino.
How can I do this?

You could create an array with the newly created directories, and then loop over this array:
#!/bin/bash
set -o errexit # Exit the script in case of error
# Pre-declare and empty array.
declare -a new_directories;
# Save other scripts path for later use.
getHGSVposHG19="${pwd}/getHGSVposHG19.sh"
getChromosomicPositions="${pwd}/getChromosomicPositions.sh"
getHaplotypeStrings="${pwd}/getHaplotypeStrings.sh"
# Create missing directories
for fname in *.xlsx *csv
do
dname=${fname%.*}
if [ ! -d $dname ]
then
mkdir "$dname";
new_directories+=("${dname}");
fi
mv "$fname" "$dname";
done
# Initialize only new directories
for geni in "${new_directories[#]}"
do
pushd "${geni}"; # Add to directory stack
export pippo="$(basename $(pwd))";
export z=$(tail -n 1 *.csv | tr ';' "\n" | wc -l)
"${getChromosomicPositions}" *.csv;
export z; # Is the previous script modifying z?
"${getHaplotypeStrings}" *.csv;
popd; #Remove from directory stack
done
I also took the liberty to clean your script a bit, since I can't run it as is, it might have some typos/bugs...
What is pushd and popd?

Related

bash - how to grep a string within a file and index with the file name

I have a few thousand files each within their own folder and I want to link a specific string ID with the file name.
So for example here I have a couple of different folders :
Folder_1
file_abc.txt
Sample-001-abc
Folder_2
file_efg.txt
Sample-002-efg
Folder_3
file_hig.txt
Sample-003-hig
and I would like to grep based on the string "Sample" and link that string to the filename each is located in, to ensure I have the correct sample/filename order. Essentially, I would like to output a separate file that looks like this:
Filename_sample_linked.txt
file_abc.txt Sample-001-abc
file_efg.txt Sample-002-efg
file_hig.txt Sample-003-hig
...etc
I can grab all the IDs with the following:
find dir/*.txt -type f -exec grep -H 'Sample' {} + >> List_of_samples.txt
but am not quite sure how to link that with the file name that the string came from. Thanks in advance for your help!
Maybe sed.
If you actually meant for that filename to be line 1:
$: sed -E '1{s/.*/Filename_sample_linked.txt/;p;d}; /[.]txt/{N;s/\n/ /}; /^$/{N;d}' file
Filename_sample_linked.txt
file_abc.txt Sample-001-abc
file_efg.txt Sample-002-efg
file_hig.txt Sample-003-hig
Otherwise, replace 1{s/.*/Filename_sample_linked.txt/;p;d}; with just 1d; maybe.
I will assume you did NOT mean for the last line to literally be ...etc.
TLDR;
generate a script via "meta programming"
run it
save the output
Sometimes, if you can solve a problem by doing simple steps repetitively, then all you need to do is figure out the steps and repeat them. The advantage of this approach is that it's not very sophisticated and relatively easy to do.
go to the folder
list the two files side by side
save that to a list
In shell-speak, that could look like this:
cd Folder_1; echo file_* Sample*; cd ..
cd Folder_3; echo file_* Sample*; cd ..
I can show you how to do this many times, but first let's have some fun.
setup.sh
#!/bin/bash
md () { mkdir -p "$1"; cd "$1"; pwd; }
ran3() { tr -dc '[[:alnum:]]' </dev/urandom | dd bs=${1:-3} count=1 status=none ; }
w80() { echo $(( 20 + 80 * RANDOM / 65536 )); }
w20() { echo $(( 3 + 20 * RANDOM / 65536 )); }
# Initial setup
md Folder_1
touch file_abc.txt
touch Sample-001-abc
cd ..
md Folder_2
touch file_efg.txt
touch Sample-002-efg
cd ..
md Folder_3
touch file_hig.txt
touch Sample-003-hig
cd ..
# More folders with 3-char comparison patterns
s=0
s=$( find -name Sample\* | wc -l )
(( s++ ))
max=$(( s + 20 ))
while [[ $s -lt $max ]]; do
md Folder_$s
str=`ran3`
printf -v ss '%03d' $s
touch file_$str.txt
touch Sample-$ss-$str
(( s++ ))
cd ..
done
# More folders with random names
max=$(( max + 20 ))
while [[ $s -lt $max ]]; do
fstr=`ran3 $(w80)`
md ${fstr}_$s
str=`ran3 $(w20)`
printf -v ss '%03d' $s
touch file_$str.txt
touch Sample-$ss-$str
(( s++ ))
cd ..
done
I ran that a few times and now I have:
./Folder_143/file_nhE.txt
./Folder_143/Sample-143-nhE
./yHb9aSWkRDXqQfITkrqplQQMH[cNdMTYt_144/file_W9eDdDIEN.txt
./yHb9aSWkRDXqQfITkrqplQQMH[cNdMTYt_144/Sample-144-W9eDdDIEN
./ClauM57QCXPCqLPBHUMERI6Vxc_145/file_vhTSZfTh.txt
./ClauM57QCXPCqLPBHUMERI6Vxc_145/Sample-145-vhTSZfTh
./kpXndK8eapnUJKf9XvFZgnY31kUVNmUkHDp1ey[Q3IsY53EOQ_146/file_b[rj3ft.txt
./kpXndK8eapnUJKf9XvFZgnY31kUVNmUkHDp1ey[Q3IsY53EOQ_146/Sample-146-b[rj3ft
./mx]Yrj5eEa4PlEL2snmYOttZwc]Vi4rSCJ_147/file_]OyWwrVd0RN.txt
./mx]Yrj5eEa4PlEL2snmYOttZwc]Vi4rSCJ_147/Sample-147-]OyWwrVd0RN
./Zpi1sip87UmM85gd[dh]9sQn5ZE5rjBGA[[9ae_148/file_uQPZU[Tn[.txt
step 1 (generate the meta script)
find -name Sample\* -type f \
-printf "cd $PWD"';s="%f"; cd %h ; echo file_${s##*-}.txt %f\n'
Here we use find to make a bunch of commands for us, that we can run. Mixing quotes like "ABC"'123' into a single string ABC123 is just a clever way to interpolate some variables, while passing others to -printf for later.
"cd $PWD"
Go to the base folder before each sub-folder.
';s="%f"; cd %h ;
End the cd-pwd and asign the basename to s.
Go to the dirname of each found Samlple* file.
echo file_${s##*-}.txt %f\n'
Print the two files side by side.
${s##GLOB} means remove everything from the start of the s string that matches GLOB. So effectively remove everything up to and with the last dash.
The %f and %h macros are available when using find -printf, if that was unclear.
cd /home/jaroslav/tmp/so-link;s="Sample-138-Lj]"; cd ./Folder_138 ; echo file_${s##*-}.txt Sample-138-Lj]
cd /home/jaroslav/tmp/so-link;s="Sample-139-pad"; cd ./Folder_139 ; echo file_${s##*-}.txt Sample-139-pad
cd /home/jaroslav/tmp/so-link;s="Sample-140-ImN"; cd ./Folder_140 ; echo file_${s##*-}.txt Sample-140-ImN
cd /home/jaroslav/tmp/so-link;s="Sample-141-nxr"; cd ./Folder_141 ; echo file_${s##*-}.txt Sample-141-nxr
cd /home/jaroslav/tmp/so-link;s="Sample-142-4Di"; cd ./Folder_142 ; echo file_${s##*-}.txt Sample-142-4Di
cd /home/jaroslav/tmp/so-link;s="Sample-143-nhE"; cd ./Folder_143 ; echo file_${s##*-}.txt Sample-143-nhE
cd /home/jaroslav/tmp/so-link;s="Sample-144-W9eDdDIEN"; cd ./yHb9aSWkRDXqQfITkrqplQQMH[cNdMTYt_144 ; echo file_${s##*-}.txt Sample-144-W9eDdDIEN
cd /home/jaroslav/tmp/so-link;s="Sample-145-vhTSZfTh"; cd ./ClauM57QCXPCqLPBHUMERI6Vxc_145 ; echo file_${s##*-}.txt Sample-145-vhTSZfTh
cd /home/jaroslav/tmp/so-link;s="Sample-146-b[rj3ft"; cd ./kpXndK8eapnUJKf9XvFZgnY31kUVNmUkHDp1ey[Q3IsY53EOQ_146 ; echo file_${s##*-}.txt Sample-146-b[rj3ft
Keep in mind that this solution is fragile and relies on the regularity of the names of the input files / folders. If you are working with unpredictable data, you may need to think harder...
step 2 (run the meta script)
$ find -name Sample\* -type f \
-printf "cd $PWD"';s="%f"; cd %h ; echo file_${s##*-}.txt %f\n' \
| bash -x
cd /home/jaroslav/tmp/so-link;s="Sample-001-abc"; cd ./Folder_1 ; echo file_${s##*-}.txt Sample-001-abc
cd /home/jaroslav/tmp/so-link;s="Sample-002-efg"; cd ./Folder_2 ; echo file_${s##*-}.txt Sample-002-efg
cd /home/jaroslav/tmp/so-link;s="Sample-003-hig"; cd ./Folder_3 ; echo file_${s##*-}.txt Sample-003-hig
(...)
+ cd './v0a7F1K5P[fKL5NSYXaMZdFdGV7UCK_154'
+ echo file_R0IZENm2ni.txt Sample-154-R0IZENm2ni
file_R0IZENm2ni.txt Sample-154-R0IZENm2ni
+ cd /home/jaroslav/tmp/so-link
+ s=Sample-155-MEuAFsvztX
+ cd ./tKUlAFlPy2zq2xiZhruhS9U2VDnNQc7LiwYkUxL_155
+ echo file_MEuAFsvztX.txt Sample-155-MEuAFsvztX
file_MEuAFsvztX.txt Sample-155-MEuAFsvztX
+ cd /home/jaroslav/tmp/so-link
+ s='Sample-156-M7e]VOOHFz'
+ cd './3zVn7Z9ltN2MpmS[lo]6DCgv4RFEdX9XDoskFY0p_156'
+ echo 'file_M7e]VOOHFz.txt' 'Sample-156-M7e]VOOHFz'
file_M7e]VOOHFz.txt Sample-156-M7e]VOOHFz
(...)
step 3 (save the output)
$ find -name Sample\* -type f \
-printf "cd $PWD"';s="%f"; cd %h ; echo file_${s##*-}.txt %f\n' \
| bash | column -t \
| tee /tmp/list
(...)
file_ImN.txt Sample-140-ImN
file_nxr.txt Sample-141-nxr
file_4Di.txt Sample-142-4Di
file_nhE.txt Sample-143-nhE
file_W9eDdDIEN.txt Sample-144-W9eDdDIEN
file_vhTSZfTh.txt Sample-145-vhTSZfTh
file_b[rj3ft.txt Sample-146-b[rj3ft
file_]OyWwrVd0RN.txt Sample-147-]OyWwrVd0RN
(...)
From here you can sort the output or whatever else you need
$ cat /tmp/list | sed 's/\ \+/ /' | sort -b -k2.9,2.14n --debug
_________________________________________
file_M7e]VOOHFz.txt Sample-156-M7e]VOOHFz
___
_________________________________________
file_ftb8ifOfYt.txt Sample-157-ftb8ifOfYt
___
_________________________________________
file_tWOa]ZbTA.txt Sample-158-tWOa]ZbTA
___
_______________________________________
file_n4s2Znk.txt Sample-159-n4s2Znk
___
___________________________________
file_mjMox[P.txt Sample-160-mjMox[P
___
___________________________________
file_tQ3.txt Sample-161-tQ3
___
___________________________
file_G6VFcFHYH.txt Sample-162-G6VFcFHYH
___
_______________________________________
file_4mXCFTZaC.txt Sample-163-4mXCFTZaC
___
_______________________________________

How to create a bash script to make directories and specific files inside each directory

I wrote a bash script trying to generate one directory named after each file inside the directory from which I run the script.
Original directory= /home/agalvez/data//sims/phylip_format
sim1.phylip
sim2.phylip
Directories to create = sim1 sim2
The contents of these new directories should be a copy of the original file that names the new directory and an extra file called "input". This file should contain the name of the .phylip file as well as the following:
"Name of original file"
U
5
Y
/home/agalvez/data/sims/trees/tree_nodenames.txt
After that I want to run the following command (sequentially) in all these new directories:
phylip dollop < input > screenout
My approach is the following one but it is not working:
!/bin/bash
for f in *.phylip;
mkdir /home/agalvez/data/sims/dollop/$f;
cp $f /home/agalvez/data/sims/dollop/$f;
cd /home/agalvez/data/sims/dollop/$f;
echo "$f" | cat > input;
echo "U" | cat >> input;
echo "5" | cat >> input;
echo "Y" | cat >> input;
echo "/home/agalvez/data/sims/trees/tree_nodenames.txt" | cat >> input;
phylip dollop < input > screenout;
;done
Edit: The error messge looks like this:
line 4: syntax error near unexpected token `mkdir'
line 4: ` mkdir /home/agalvez/data/sims/dollop/$f;'
FINAL SOLUTION:
#!/bin/bash
for f in *.phylip;
do
mkdir /home/agalvez/data/sims/dollop/$f;
cp /home/agalvez/data/sims/phylip_format/$f /home/agalvez/data/sims/dollop/$f;
cd /home/agalvez/data/sims/dollop/$f;
echo "$f" | cat > input;
echo "U" | cat >> input;
echo "5" | cat >> input;
echo "Y" | cat >> input;
echo "/home/agalvez/data/sims/trees/tree_nodenames.txt" | cat >> input;
phylip dollop < input > screenout;
done
The immediate problem is that you are lacking a do at the beginning of the loop body; but you'll want to refactor this code to avoid hardcoding the directory structure etc.
The first line needs to start with literally the two characters # and ! in order to be a valid shebang.
Notice also When to wrap quotes around a shell variable?
The printf could be replaced with a here document; I like the compactness of printf here.
#!/bin/bash
for f in *.phylip; do
mkdir -p dollop/"$f"
cp "$f" dollop/"$f"
cd dollop/"$f"
printf "%s\n" "$f" "U" "5" "Y" \
"/home/agalvez/data/sims/trees/tree_nodenames.txt" |
phylip dollop > screenout
done
Going forward, try http://shellcheck.net/ for diagnosing many common beginner problems in shell scripts.
Assuming you have a directory named pingping in your ${HOME} folder with files 1.txt, 2.txt, 3.txt. You can accomplish that like this. Modify this code to suit your needs.
#! /bin/bash
working_directory="${HOME}/pingping/"
cd $working_directory
for f in *.txt
do
mkdir "${f%%.*}"
if [ -f "${f%%.*}.txt" ]
then
if [ -d "${f%%.*}" ]
then
cp ${f%%.*}.txt ${f%%.*}
echo "Done copying"
#phylip dollop < input > screenout
#echo "Succesfully ran the command
fi
else
echo "not found"
fi
done

Merge two directories keeping larger files

Consider for example
mkdir dir1
mkdir dir2
cd dir1
echo "This file contains something" > a
touch b
echo "This file contains something" > c
echo "This file contains something" > d
touch e
cd ../dir2
touch a
echo "This file contains something" > b
echo "This file contains something" > c
echo "This file contains more data than the other file that has the same name but is in the other directory. BlaBlaBlaBlaBlaBlaBlaBlaBla BlaBlaBlaBlaBlaBlaBlaBlaBla BlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBla. bla!" > d
I would like to merge dir1 and dir2. If two files have the same name, then only the one which size is the largest must be kept. Here is the expected content of the merged directory
a # Comes from `dir1`
b # Comes from `dir2`
c # Comes from either `dir1` or `dir2`
d # Comes from `dir2`
e # Comes from `dir1`(is empty)
Assuming that no file name a newline:
find . -type f -printf '%s %p\n' \
| sort -nr \
| while read -r size file; do
if ! [ -e "dest/${file#./*/}" ]; then
cp "$file" "dest/${file#./*/}";
fi;
done
The output of find is a list of "filesize path":
221 ./dir1/a
1002 ./dir1/b
11 ./dir2/a
Then we sort the list numeric:
1002 ./dir1/b
221 ./dir1/a
11 ./dir2/a
And fianlly we reach the while read -r size filename loop, where each file is copied over to the destination dest/${file#./*/} if they don't already exists.
${file#./*/} expands to the value of the parameter file with the leading directory removed:
./abc/def/foo/bar.txt -> def/foo/bar.txt, which means you might need to create the directory def/foo in the dest directory:
| while read -r size file; do
dest=dest/${file#./*/}
destdir=${dest%/*}
[ -e "$dest" ] && continue
[ -e "$destdir" ] || mkdir -p -- "$destdir"
cp -- "$file" "$dest"
done
I cannot comment on the other answer due to not enough reputation, but I was getting a syntax error due to missing fi. I also got an error where the target directory needed to be created before copying. So:
find . -type f -printf '%s %p\n' | sort -nr | while read -r size file; do if ! [ -e "dest/${file#./*/}" ]; then mkdir -p "$(dirname "dest/${file#./*/}")" && cp "$file" "dest/${file#./*/}"; fi; done

Separate folders into subfolders according to numbering in bash

I have the following directory tree:
1_loc
2_buzdfg
4_foodga
5_bardfg
6_loc
8_buzass
9_foossd
12_bardaf
There may be numbers missing in the folder ordering.
I want to separate these folders into subfolders according to their numbers, so that all folders with a number smaller than 6 (before the second _loc folder) would go to folder1 and all folders with a number equal or greater than 6 with go to folder2.
I can solve the problem very easily using the mouse, of course, but I wanted a suggestion of how to do this automatically from the terminal.
Any ideas?
while read -r line; do
# Regex match the beginning of the string for a character between 1 and 5 - change this as you'd please to any regex
FOLDERNUMBER=""
[[ "$line" ~= "^[1-5]" ]] && FOLDERNUMBER="1" || FOLDERNUMBER="2"
# So FOLDERPATH = "./folder1", if FOLDERNUMBER=1
FOLDERPATH="./folder$FOLDERNUMBER"
# Check folder exists, if not create it
[[ ! -d "$FOLDERPATH" ]] && mkdir "$FOLDERPATH"
# Finally, move the file to FOLDERPATH
mv "$line" "$FOLDERPATH/$(basename $line)"
done < <(find . -type f)
# This iterates through each line of the command in the brackets - in this case, each file path from the `find` command.
I think the solution is to loop through the files and check the number before the first _.
Firstly, let's check how to get the number before _:
$ d="1_loc_b"
$ echo "${d%%_*}"
1
OK, so this works. Then, let's loop:
for file in *
do
echo "$file"
(( ${file%%_*} > 5)) && echo "moving to dir2/" || echo "moving to dir1/"
done
Suppose folder1 and folder2 exists in the same directory, I will do it like this:
for d in *_*; do # to avoid folder1 and folder2
# check if the first field seperated by _ is less than 5
if ((`echo $d | cut -d"_" -f1` < 6)); then
mv $d folder1/$d;
else
mv $d folder2/$d;
fi;
done
(more about cut)
You can go to the current directory and run these simple commands:
mv {1,2,3,4}_* folder1/
mv {5,6,7,8}_* folder2/
This assumes no other files/directory starting with these prefixes (i.e. 1-8).
Another pure bash, parameter-expansion solution:-
#!/bin/bash
# 'find' returns folders having a '_' in their names, the flag -print0 option to
# preserve special characters in names.
# the folders are names as './1_folder', './2_folder', bash magic is done
# to remove those special characters.
# '-v' flag in 'mv' for verbose action
while IFS= read -r -d '' folder; do
folderName="${folder%_*}" # To strip the characters after the '_'
finalName="${folderName##*/}" # To strip the everything before '/'
((finalName > 5)) && mv -v "$folder" folder1 || mv -v "$folder" folder2
done < <(find . -maxdepth 1 -mindepth 1 -name "*_*" -type d -print0)
You can create the a script with the following code and when you run it, the folders will be moved as desired..
#seperate the folders into 2 folders
#this is a generic solution for any folder that start with a number
#!/bin/bash
for file in *
do
prefix=`echo $file | awk 'BEGIN{FS="_"};{print $1}'`
if [[ $prefix != ?(-)+([0-9]) ]]
then continue
fi
if [ $prefix -le 4 ]
then mv "$file" folder1
elif [ $prefix -ge 5 ]
then mv "$file" folder2
fi
done

Move files from directories listed in file

I have a directory structure like the following toy example
DirectoryTo
DirectoryFrom
-Dir1
---File1.txt
---File2.txt
---File3.txt
-Dir2
---File4.txt
---File5.txt
---File6.txt
-Dir3
---File1.txt
---File5.txt
---File7.txt
I'm trying to copy all the files from DirectoryFrom to DirectoryTo, keeping the newer file if there are duplicates.
DirectoryTo
-File1.txt
-File2.txt
-File3.txt
-File4.txt
-File5.txt
-File6.txt
-File7.txt
DirectoryFrom
-Dir1
---File1.txt
---File2.txt
---File3.txt
-Dir2
---File4.txt
---File5.txt
---File6.txt
-Dir3
---File1.txt
---File5.txt
---File7.txt
I've created a text file with a list of all the subdirectories. This list is in the order such that the NEWEST files will be listed first:
Filelist.txt
C:/DirectoryFrom/Dir1
C:/DirectoryFrom/Dir2
C:/DirectoryFrom/Dir3
So what I'd like to do is loop through each directory in Filelist.txt, copy the files, and NOT replace if the file already exists.
I'd like to do this at the command line, in a shell script, or possibly in Python. I'm pretty new to Python, but have a little experience with the command line. However, I've never done something this complicated.
In reality, I have ~60 folders, each with 50-200 files in them, to give you a feel for how many I have. Also, each file is ~75MB.
I've done something similar in R before, but it's slow and not really meant for this. But here's what I've tried for a shell script, edited to fit this toy example:
#!/bin/bash
for line in Filelist.txt
do
cp -n line C:/DirectoryTo/
done
If you have only one one directory level in your DirectoryFrom then you can use:
cp -n DirectoryFrom/*/* DirectoryTo
explanation : copy every file which exist in subdirectories of DirectoryFrom to DirectoryTo if it doesn't exist
n flag is for not overwriting files if they already exist.
cp will also ignore directories if they exist in subdirectories of DirectoryTo
# Create test environnement :
mkdir C:/DirectoryTo
mkdir C:/DirectoryFrom
cd C:/DirectoryFrom
mkdir Dir1 Dir2 Dir3
(
cat << EOF
Dir1/File1.txt
Dir1/File2.txt
Dir1/File3.txt
Dir2/File4.txt
Dir2/File5.txt
Dir2/File6.txt
Dir3/File1.txt
Dir3/File5.txt
Dir3/File7.txt
EOF
)| while read f
do
echo "$f : `date`"
echo "$f : `date`" > $f
sleep 1
done
# create Filelist.txt file :
(
cat << EOF
C:/DirectoryFrom/Dir1
C:/DirectoryFrom/Dir2
C:/DirectoryFrom/Dir3
EOF
) > Filelist.txt
# Generate the liste of all files :
cd C:/DirectoryFrom
cat Filelist.txt | while read f; do ls -1 $f; done | sort -u > filenames.txt
cat filenames.txt
# liste of all files path, sorted by time order :
cd C:/DirectoryFrom
ls -1tr */* > all_filespath_sorted.txt
cat all_filespath_sorted.txt
# selected files to be copied :
cat filenames.txt | while read f; do cat all_filespath_sorted.txt | grep $f | tail -1 ; done
# copy of selected files:
cat filenames.txt | while read f; do cat all_filespath_sorted.txt | grep $f | tail -1 ; done | while read c
do
echo $c
cp -p $c C:/DirectoryTo
done
# verifying :
cd C:/DirectoryTo
ls -ltr
# or
ls -1 | while read f; do echo -e "\n$f\n-------"; cat $f; done
#------------------------------------------------
# Other solution for a limited number of files :
#------------------------------------------------
# To list files by order :
find `cat Filelist.txt | xargs` -type f | xargs ls -1tr
# To copy files, the newer will replace the older :
find `cat Filelist.txt | xargs` -type f | xargs ls -1tr | while read c
do
echo $c
cp -p $c C:/DirectoryTo
done

Resources