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.

user206217
  • 21
  • 1
  • 6
  • 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 08 '19 at 15:13
  • Are you on Windows? Those are Windows paths (`\foo\bar`) and not Linux ones (`/foo/bar`). – terdon Jan 08 '19 at 15:13
  • The original files are on a Windows machine, but I've copied it all over to my Ubuntu laptop to work on - the CSV file is used to specify the path and filename in a piece of software that runs on the Windows machine though, so it uses \, but yeah, I got confused as well :) – user206217 Jan 08 '19 at 15:26
  • @RoVo - that looks like it works - I get feedback such as user@Laptop:~/Desktop/images$ sed 's/"//g;s/\\/\//g' files.csv | while IFS=, read orig new; do echo mv "$orig" "$new"; done mv /00101191/ABC123.jpg /House/MoneyBoxABC123.jpg but the files are still named the same thing at the end. I have also tried changing all the \ for / in the CSV but I get the same result. I thought perhaps this may be because the directories don't exist, but even if I create them manually it doesn't seem to do anything. – user206217 Jan 08 '19 at 15:43
  • You use `echo mv ... ` and it just prints `mv ... `? I think this is intended, you need to remove `echo` if you want the magic to happen. – pLumo Jan 08 '19 at 15:45
  • 2
    Are your files are actually rooted at absolute path `/`, or are they relative to your current directory? – steeldriver Jan 08 '19 at 15:48
  • Please [edit] your question and show us some _actual_ lines from the csv file so we don't need to guess. – terdon Jan 08 '19 at 16:06
  • what is the output of `ls /00101234/1101.jpg` ? – pLumo Jan 08 '19 at 16:39
  • 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 08 '19 at 16:53
  • @terdon, sadly, yes. Some users have added images in directories based on the computer generated id of the supplier (e.g. 00101234) and some have added them based on the type of product (e.g. Jewellery) The images themselves are sometimes of the form ProductCode.jpg, and sometimes Description.jpg, and sometimes I've no idea why they are called what they are called - I'm making them all DescriptionProductCode.jpg in to directories named for the type of procuct. – user206217 Jan 08 '19 at 17:00
  • @Rovo I get ls: cannot access '/00101234/1101.jpg': No such file or directory - but the file is there – user206217 Jan 08 '19 at 17:00
  • 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 08 '19 at 17:04
  • Personnaly, if it's a a one-shot thing, I would edit the CSV to make it a script, with a "mv" command per line, and then "source" it. – xenoid Jan 08 '19 at 21:47
  • 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 09 '19 at 14:29

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
  • 39,392
  • 12
  • 115
  • 163
terdon
  • 98,183
  • 15
  • 197
  • 293
  • 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 09 '19 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
dessert
  • 39,392
  • 12
  • 115
  • 163
wjandrea
  • 14,109
  • 4
  • 48
  • 98
  • 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 09 '19 at 14:28