-2

I have a directory with around 2000 files in it.

~/
-File 1.pdf
-File2.pdf
-Another file 1.pdf
-File3.pdf
-Someother file.docx
-Yeanother.pdf 

I have mapped each file with the account it relates to. This mapping is in a CSV file.

File Name & Destination

File 1.pdf          | CompanyAccount1
File2.pdf           | CompanyAccount1
Another file 1.pdf  | CompanyAcountA
File3.pdf           | CompanyAccount5
Someother file.docx | AnotherAccount2
Yeanother.pdf       | CompanyAccount1

I would like to move the files from the main directory into sub-directories based on the account name based on the csv (or text file).

Desired Result

~/
-CompanyAccount1
--File 1.pdf
--File2.pdf
--Yeanother.pdf
-CompanyAcountA
--Another file 1.pdf
-CompanyAccount5
--File3.pdf 
-AnotherAccount2
--Someother file.docx

Ideally it would be something as simple as mv < file-and-destination.csv, but I can't get it to work. I've tried xargs mv < renaming.txt, but it doesn't work as expected (some were moved and then everything else was moved into a single directory).

  • 2
    Please share what you tried... – NaN Jul 25 '18 at 13:19
  • 1
    and some working example...also when you say that the files "relates to" an account, do you mean "owned by" ? – Andre Gelinas Jul 25 '18 at 13:34
  • Loop on the CSV, read the values (account and filename), create directory "account" if it does not exist, move "filename" into that directory, keep looping. No attempt, no free code :-) – Nic3500 Jul 25 '18 at 13:44
  • I've done a lot of variations on this, xargs -I {} mv {} < renaming.txt, an Apple Script, a bash script. I can put the things I've tried, but they are variations of things i've pulled off of stack overflow and other forums, so I don't see the value. Most sites deal with moving files in a list into one directory, but I have not seen both the source and destination from a text file, so I thought it useful to ask here in case others run into it. – Heath Weaver Jul 25 '18 at 13:56

1 Answers1

0

Create the directories:

cut -f2 file-and-destination.csv |
xargs mkdir -p

This assumes the text is tab-delimited, and that no filenames contain a tab.

If none of the file names contained whitespace, you could simply xargs -n 2 mv <file-and-destination.csv but the way it is now (assuming your sample is representative), a simple while IFS=$'\t' read -r file dir loop seems like the way to go.

while IFS=$'\t' read -r file dir; do
    mv "$file" "$dir"
done <file-and-destination.csv

Another solution is to generate a script to generate the directories and move the files. This one assumes there are no file names with single quotes in them, either;

sed $'s/\\([^\t]*\\)\t\\(.*\\)/mkdir -p \'\\2\'; mv \'\\1\' \'\\2\''

This just generates the commands; pipe to sh if the result looks reasonable.

I use Bash "C-style strings $'...' throughout as a convenience. If you don't have Bash, the second one in particular will require some refactoring. In the first, you should be able to simply drop the dollar sign and type a literal tab between the single quotes (in many shells, control-v tab to get a literal tab character on the command line).

All in all, I would not recommend the latter technique. If you have control over the input file format, simply putting destdir/file to say that file should be moved to destdir might be a better design (because splitting on a slash is easy and natural, and now you can have file names with tabs, too).

tripleee
  • 175,061
  • 34
  • 275
  • 318
  • The first solution works. I added a mkdir command into the loop, but your solution is better to avoid getting a bunch of errors for when multiple files go into a single directory. I've also changed the tab to a pipe as it made it much easier. – Heath Weaver Jul 26 '18 at 11:31