2

I have a bunch of files each in their own subdirectory. I need to write a script to rename each file to have the same name as its directory: For example, given:

./1111/1234.pdf
./2222/2345.pdf
./1234/3214.pdf

I need them to be renamed to:

./1111/1111.pdf
./2222/2222.pdf
./1234/1234.pdf

How can I do that?

  • Doesn't happen to be homework? – Hauke Laging Jun 10 '13 at 20:36
4

Assuming your shell is zsh, put autoload -U zmv in your ~/.zshrc, and run

zmv '(*)/*.pdf' '$1/$1.pdf'
2

The following bash script does the job when invoked in the parent directory. It does so even when the files don't all have the same extension (they do in your limited example, but that might be a coincidence):

#!/bin/bash
function dirnametofilename() {
  for f in $*; do
    bn=$(basename "$f")
    ext="${bn##*.}"
    filepath=$(dirname "$f")
    dirname=$(basename "$filepath")
    mv "$f" "$filepath/$dirname.$ext"
  done
}

dirnametofilename ./????/*

the invocation there assumes any file in a subdirectory of the current directory which has a name with four characters. You can exchange the last line with:

dirnametofilename $*

and specify the filenames as parameters to the script


The following creates a somewhat deeper hierarchy and uses find to locate the files. The export -f make sure the bash started by find knows about the function:

mkdir -p x/y/z/1111 x/y/z/2222 x/y/z/1234
touch x/y/z/1111/1234.pdf
touch x/y/z/2222/2345.pdf
touch x/y/z/1234/3214.pdf

function dirnametofilename() {
  for f in $*; do
    bn=$(basename "$f")
    ext="${bn##*.}"
    filepath=$(dirname "$f")
    dirname=$(basename "$filepath")
    mv "$f" "$filepath/$dirname.$ext"
  done
}

export -f dirnametofilename

find . -name "*.pdf" -exec bash -c 'dirnametofilename "{}"'  \;
# and look at the result
find x
  • what if you need to run this in directory x from:/x/y/z/1111/1234.pdf – Duy Jun 13 '13 at 12:23
  • just feed the function the whole path y/z/1111/1234.pdf it will rename to y/z/1111/1111.pdf. Use e.g. find to locate the files (echo first to see if you got the right set of names, then subsitute the echo with the function call). – Anthon Jun 13 '13 at 12:58
  • @duy extended the answer, hope you can get it to work this way. – Anthon Jun 13 '13 at 13:14
0
echo ./1111/1234.pdf | perl -pe '$_.=$_; s/\/(.*?)\/.+\.(.*?)$/\/$1\/$1\.$2/' | xargs -n 2 mv

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.