1

I am trying to rename files and append their parent directory name to them (and move them to a new folder named Photos).

I've been trying to do this with rename and mmv, but I am having difficulties doing this when standing inside directory A in the example below.

$ pwd
/A
$ tree
.
├── 1.jpg
├── 2.jpg
└── 3.jpg

But it works fine when running rename from one step higher up in the folder hierarchy.

$ pwd
/
$ tree
.
└── A
    ├── 1.jpg
    ├── 2.jpg
    └── 3.jpg

$ rename 's|(.*)/(.*)|$1/Photos/$1 - $2|' */*.jpg -p
$ tree
.
└── A
    └── Photos
        ├── A\ -\ 1.jpg
        ├── A\ -\ 2.jpg
        └── A\ -\ 3.jpg

How can this be accomplished when standing in directory 'A' in the example?

2 Answers 2

1

OK that's a fancier rename than what I have, so first try using sed:

Dir=$(basename "$PWD")
mkdir -p Photos
ls *.jpg|sed 's|\(.*\)|mv "\1" "Photos/'"$Dir"' - \1"|'    |sh

which I guess translates to your rename like this:

Dir=$(basename "$PWD")
rename 's|(.*)|Photos/'"$Dir"' - $1|' *.jpg -p
2
  • Thanks for the classic method. I've never seen something piped to sh before. Could you elaborate a little how that sed command works with mv inside? I also did som further experiments with the rename command. I write in a separate post for readability.
    – Kasam
    Commented Oct 22, 2022 at 16:12
  • Using the sed route, I should warn that you probably want to be sure that some attacker can't get to your filenames and do bad things since the filenames go into shell commands! Anyway, the sed is just taking the filename and putting each into it's own mv command. For testing you can leave out the |cat to see what commands are generated, then add it once you are happy with what you see. Commented Oct 28, 2022 at 12:17
0

Expanding upon AndreBeaud's answer. I also did some further experiments with the rename command. These four variants all work, it can probably be done even cleaner. I noticed that AndreBeaud didn't use eval, instead used single quotes to concatenate the strings. Handy.

  1. Short but kind of difficult to read.

    rename 's|.*/(.*)/(.*)|Photos/$1 - $2|' `pwd`/*.jpg --make-dirs
    
  2. Easier to read with the folder name in the substitute part.

    eval "rename 's|(.*)|Photos/$(basename `"pwd"`) - \$1|' *.jpg --make-dirs"
    
  3. Create variable first. Not critical in this case, since it's only used once. Easy to follow.

    Dir=$(basename `"pwd"`); eval "rename 's|(.*)|Photos/$Dir - \$1|' *.jpg --make-dirs"
    
  4. Variable first, but with the folder name in the find part, messy.

    Dir=$(basename `"pwd"`); rename 's|.*/(.*)/(.*)|Photos/$1 - $2|' ../$Dir/*.jpg --make-dirs
    

Combining both AndreBeaud's and my versions can make this short version:

rename 's|(.*)|Photos/'"$(basename "$PWD")"' - $1|' *.jpg --make-dirs

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .