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.

  • paths in Linux use slash instead of backslash. Adding ;s/\\/\//g to your sed command should do it. ==> sed 's/"//g;s/\\/\//g' files.csv | ... – pLumo Jan 8 at 15:13
  • 2
    Are your files are actually rooted at absolute path /, or are they relative to your current directory? – steeldriver Jan 8 at 15:48
  • 1
    And do you really have a directory called /00101234/? And one called /jewlery? What is the output of ls -ld /00101234 /jewlery? – terdon Jan 8 at 16:53
  • 1
    Please add the output of the command I asked for. If you're getting "no such file" then there is no such directory, which is why I asked in my previous comment. /foo is the equivalent of C:\foo and I think you want paths relative to your home directory. So, please edit your question and show us ls -ld /00101234 /Jewlery which will tell us if those directories exist. – terdon Jan 8 at 17:04
  • 1
    You didn't copy the command correctly. You are trying to execute the image file: orig.jpg new.jpg and not move it. You need the mv command to move it: mv orig.jpg new.jpg. Read my answer again and copy the command correctly: while IFS=, read -r orig new; do mv "/home/me/Images$orig" "/home/me/Images/NEW$new"; done < files.csv – terdon Jan 9 at 14:29
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.

  • This did not work for me @terdon, and I've not been able to work out why. I just get 'me@laptop:~/Desktop/images$ tr -d '\r' < files.csv | while IFS=, read -r old new; do mv "~/Desktop/images${old}" "~/Desktop/images/Jewlery${new}"done < files.csv > ' i.e. it just hangs at > and I get no more feedback. I've added another update to the original question. Thanks again. – user206217 Jan 9 at 14:26
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
  • Thanks @wjandrea - I've used this to (I think) almost get it to work - I now just have a permision problem, which I've added to Update 4 above. Thanks again for your help. – user206217 Jan 9 at 14:28

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.