0

I have a list file with names of files, i want read one file name from the list at a time and look for it under a directory structure with multiple sub folders and then once found move it into a diff folder.

Ex:

listfile.txt

Content of the file--
filename1.txt
filename2.txt

maindir
|--subdir1
|---subdir2/filename1.txt
|---subdir3/filename2.txt

read file names from listfile.txt one by one and move them to a diff folder say /destfolder.

Any suggestion would be great.

Thanks, Kavin

1 Answers1

2

Using a shell loop and calling find once for each filename:

mkdir -p archive_dir
while IFS= read -r filename; do
    find maindir -type f -name "$filename" -exec mv {} archive_dir ';'
done <listfile.txt

This would be slightly inefficient since it would continue looking for matching filenames even after finding the file (and if it found another one, it would overwrite the one already moved).

If using GNU find, you may add -quit to the very end of the find command to make the find process stop after the first file has been moved.

Showing it works:

$ cat listfile.txt
filename1.txt
filename2.txt
.
|-- listfile.txt
`-- maindir
    |-- subdir1
    |-- subdir2
    |   `-- filename1.txt
    `-- subdir3
        `-- filename2.txt

4 directories, 3 files

(running the above loop)

Then:

.
|-- archive_dir
|   |-- filename1.txt
|   `-- filename2.txt
|-- listfile.txt
`-- maindir
    |-- subdir1
    |-- subdir2
    `-- subdir3

5 directories, 3 files

Related:

Kusalananda
  • 333,661
  • 1
    to make sure it operates only once @Kusalananda, you can use the -quit predicate if available; alternatively tack onto the -exec something that kills the grep'd PID of find. – webmarc Jun 29 '18 at 16:09
  • 1
    @webmarc Thanks. I'm on a non-GNU system, so looking up the GNU extensions doesn't come naturally. Added a note about it. – Kusalananda Jun 29 '18 at 16:12
  • @Kusalananda Thanks for the quick response. It works fine but only moves the first file from the list, doesn't move the seconds file, what could i be doing wrong ? – Kavin Palaniswamy Jun 29 '18 at 16:14
  • @KavinPalaniswamy Does the second file actually exist with the exact filename listed in the input file? – Kusalananda Jun 29 '18 at 16:15
  • @Kusalananda yes it definitely does. The file name is structured one below the other. – Kavin Palaniswamy Jun 29 '18 at 16:16
  • @KavinPalaniswamy Is your input file or your script, or both, written on a Windows machine? That would mean that each line has a trailing carriage return. That does however not explain why the first file was moved. – Kusalananda Jun 29 '18 at 16:21
  • @KavinPalaniswamy What do you mean by "The file name is structured one below the other"? – Kusalananda Jun 29 '18 at 16:22
  • 1
    @Kusalananda am sorry, i had made a mistake, it works now :) – Kavin Palaniswamy Jun 29 '18 at 16:26
  • This also worked for me for file incat filelist.txt; do find $source_path -name "$file" -print0 | xargs -0 -I {} cp {} $archive_home ; done – Kavin Palaniswamy Jun 29 '18 at 17:14
  • @KavinPalaniswamy Yes, but you will notice that it fails as soon as any filename contains spaces or globbing patterns. Also, cp does not move the file, it copies it. – Kusalananda Jun 29 '18 at 18:02
  • @KavinPalaniswamy It would likewise fail if the pathnames in $source_path and $archive_home contained spaces, as these are unquoted. – Kusalananda Jun 29 '18 at 18:13
  • @Kusalananda agreed. But my source path and archive path is always constant. And even the file names are constant only thing that changes is the daily date. So, i think it should be safe :) Thanks again! – Kavin Palaniswamy Jul 01 '18 at 16:43