1

I have a number of files in various directories e.g

\images\00101191   
\images\Books

etc.

I would like to rename these. I have exported their paths to a CSV file, which contains information in the format 'old path and name', 'new path and new name' e.g.

\00101191\XYZ123.jpg,\Homeware\TravelMugXYZ123.jpg

I have tried the command

sed 's/"//g' files.csv | while IFS=, read orig new; do mv "$orig" "$new"; done

as per this thread but it removes the slashes, so I just get errors of the form

mv: cannot stat '00101191XYZ123.jpg': No such file or directory

I expect the solution is simple, but I cannot get the syntax to work for me. Any help would be much appreciated. Thanks.

EDIT - actual lines from csv:

/00101234/1101.jpg,/Jewellery/ALittleThankYouTeacher1101.jpg
/00101234/1102.jpg,/Jewellery/ALittleThinkingOfYou1102.jpg
/00101234/1155.jpg,/Jewellery/ALittleDreamcatcher1155.jpg
/00101234/1203.jpg,/Jewellery/ALittleLuckyElephant1203.jpg

EDIT 2

ls -ld /00101234 /Jewellery
ls: cannot access '/00101234': No such file or directory
ls: cannot access '/Jewellery': No such file or directory

EDIT 3

Today I learned how little I know. Thanks for your ongoing help - I have the following output which hopefully may help?

user@Laptop:~/Desktop/images$ ls -ld /00101234 /Jewellery
ls: cannot access '/00101234': No such file or directory
ls: cannot access '/Jewellery': No such file or directory
user@Laptop:~/Desktop/images$ cd 00101234
user@Laptop:~/Desktop/images/00101234$ cd ..
user@Laptop:~/Desktop/images$ cd Jewellery
user@Laptop:~/Desktop/images/Jewellery$ cd ..
user@Laptop:~/Desktop/images$ ls -ld \00101234 \Jewellery
drwxrwxr-x 2 user user 32768 Jan  8 16:56 00101234
drwxrwxr-x 3 user user 20480 Jan  8 16:25 Jewellery

EDIT 4

I feel like I must be missing something - but using the information from @wjandrea / @dessert and @terdon I think I've got somewhere.

The command I'm using is

while IFS=, read -r orig new; do "/home/me/Images$orig" "/home/me/Images/NEW$new"; done < files.csv

I should add that I've copied the folder of files to be renamed to /home/me/Images and put the csv file there too. I added /NEW so I can easily find the renamed files, as it occurred to me that some of the folders specified in the CSV already exist and have files in.

The issue I now have is that I get the error Permission Denied, e.g.

bash: /home/me/Images/Xmas/XmasCushion.jpg: Permission denied

but I do have permission as far as my (very limited) knowledge takes me

me@laptop:~$ ls -l /home/me/Images/Xmas/
total 176
-rw-rw-rw- 1 me me 94208 Mar  5  2018 Thumbs.db
-rw-rw-rw- 1 me me 48274 Sep 13 14:34 XmasCushion.jpg
-rw-rw-rw- 1 me me 31553 Sep 13 14:34 XmasBunting.jpg

About the only thing I know to do if there is a permission issue is to sudo it, but then I get the error

bash: syntax error near unexpected token `do'

I've learned some stuff through your help -thanks all. Apologies for still not getting it to work.

2 Answers2

2

There are a few issues here. First of all, your files are not in /00101234/, / is the root directory, kinda like Windows's C:. Your files are in ~/Desktop/images/00101234/ which means /home/yourUserName/Desktop/images/ (where yourUserName is your user name). The easiest way to deal with this, therefore, is to use relative paths. For example, consider this file:

/dir1/dir2/file

That's the absolute path to file. But if you are inside the dir1 directory, you can use a path that's relative to your current location: dir2/file.

With this in mind, let's have another look at your csv file:

/00101234/1101.jpg,/Jewellery/ALittleThankYouTeacher1101.jpg

These are relative paths. You can deal with this in two ways:

  1. Move into the ~/Desktop/images directory and use the paths as they are.
  2. Convert them to absolute paths.

I will focus on 2 since it is less likely to break. This command will not actually do anything, but it will print out the list of actions to be performed (run this from the directory containing your csv file and change yourCsv.csv to the actual name of your file):

while IFS=, read -r old new; do
    echo mv "~/Desktop/images${old}" "~/Desktop/images/Jewlery${new}"
done < yourCsv.csv

On my system, using the file you provided, this prints:

mv ~/Desktop/images/00101234/1101.jpg ~/Desktop/images/Jewlery/Jewellery/ALittleThankYouTeacher1101.jpg
mv ~/Desktop/images/00101234/1102.jpg ~/Desktop/images/Jewlery/Jewellery/ALittleThinkingOfYou1102.jpg
mv ~/Desktop/images/00101234/1155.jpg ~/Desktop/images/Jewlery/Jewellery/ALittleDreamcatcher1155.jpg
mv ~/Desktop/images/00101234/1203.jpg ~/Desktop/images/Jewlery/Jewellery/ALittleLuckyElephant1203.jpg

If that prints what you want, then we're ready to go. Remove the echo (that just means "print this", so removing it will cause the loop to execute the mv command instead of just printing it).

However, and this is important, your csv is probably a bit different. I am assuming you created it in Windows, which means it will have different line endings. So, to be on the safe side, you want to run this:

tr -d '\r' < yourCsv.csv | while IFS=, read -r old new; do
    mv "~/Desktop/images${old}" "~/Desktop/images/Jewlery${new}"
done < yourCsv.csv

Of course, I strongly recommend that you first make a backup of all of these files just in case something goes wrong.

dessert
  • 40,956
terdon
  • 104,119
0

This is an XY-problem, and at the moment the solution to problem X is not clear, but the solution to problem Y is:

To prevent read interpreting backslashes, use option -r. From help read:

-r        do not allow backslashes to escape any characters

Example

Setup:

$ echo '\00101191\XYZ123.jpg,\Homeware\TravelMugXYZ123.jpg' > files.csv

Without -r:

$ while IFS=, read orig new; do echo "$orig" "$new"; done < files.csv
00101191XYZ123.jpg HomewareTravelMugXYZ123.jpg

With -r:

$ while IFS=, read -r orig new; do echo "$orig" "$new"; done < files.csv
\00101191\XYZ123.jpg \Homeware\TravelMugXYZ123.jpg
dessert
  • 40,956
wjandrea
  • 14,504