Copy batch files by renaming them with the original directory name

Asked

Viewed 1,088 times

1

Suppose I have a directory structure organized as follows on my PC:

Diretorio 01
  Arquivo 01.jpg
  Arquivo 02.jpg
  Arquivo 03.jpg
  Arquivo 04.jpg
Diretorio 02
  Arquivo 01.jpg
  Arquivo 02.jpg
Diretorio 03
  Arquivo 01.jpg
  Arquivo 02.jpg
  Arquivo 03.jpg
...
Diretorio n
  Arquivo 01.jpg
  Arquivo 02.jpg
  Arquivo 03.jpg
  Arquivo 04.jpg

Sane n different directories. Within each of them I have a variable number of files .jpg. I would like to copy these files. jpg to another folder on my computer, placing them all in the same location and renaming them as follows in the process:

Diretorio 01 Arquivo 01.jpg
Diretorio 01 Arquivo 02.jpg
Diretorio 01 Arquivo 03.jpg
Diretorio 01 Arquivo 04.jpg
Diretorio 02 Arquivo 01.jpg
Diretorio 02 Arquivo 02.jpg
Diretorio 03 Arquivo 01.jpg
Diretorio 03 Arquivo 02.jpg
Diretorio 03 Arquivo 03.jpg
...
Diretorio n Arquivo 01.jpg
Diretorio n Arquivo 02.jpg
Diretorio n Arquivo 03.jpg
Diretorio n Arquivo 04.jpg

That is, each resulting file will be named according to the source directory and the original file name. Note that file names are repeated within source directories.

Originally my files have spaces in the names, but this space does not need to be present in the final result. I mean, names can be something on the line Diretorio_01_Arquivo_01.jpg if this makes the algorithm easier to implement.

  • Just one question, the name of the directories can be random, only followed by the number? It can be something like Foo 01, Bar 100, etc.?

  • Actually directory names are random, but without numbers. Directories have people names, like Joao da Silva, Maria Oliveira, Jose de Souza and so on.

  • Then just concatenate the name of the directory with that of the photo when moving the file to the destination folder, then a simple recursive function resolves, I will try to make a response :)

  • Dear Marcus, I reviewed the code of the answer, had some problems, but now I believe that it is working well, for trying and let me know any fault you find.

1 answer

2


Assuming that the names are random, both of the folders and of the files, what will be enough will be a recursive function to grab the photos, use the cp and copy to a new destination, something like

  • /home/docs/pasta/foo.jpg /home/target/pasta_foo.jpg

The "function" inside the bash could look something like move_recursive, then with the command cp will move the file to the desired destination (you can exchange for mv if you want to move at once, which I don’t recommend because the script hasn’t been 100% tested), then this:

echo "cp \"$file\" \"${destination_path}${only_dirname}_${only_filename}\""

Should be this:

cp "$file" "${destination_path}${only_dirname}_${only_filename}"

Or this:

mv "$file" "${destination_path}${only_dirname}_${only_filename}"

Note that I used ${...} to be able to work with the underline, because if you did that $only_dirname_$only_filename would fail.

I put in a echo the command cp to avoid running without being sure that it worked, look at the result of all command and know if it is running correctly

To get only the name of the file or folder I used:

$(basename $current_path)

The whole script should look like this:

#!/bin/bash

# "função" para recursividade
move_recursive() {
    echo ""
    echo "-------------------------"
    echo "Lendo pasta: $path"
    echo "-------------------------"

    current_path="$1"

    for file in "$1"/*
    do
        if [ -d "$file" ]
        then
            move_recursive "$file"
        elif [ -f "$file" ]
        then
            only_dirname=$(basename $current_path)
            only_filename=$(basename "$file")

            # tire do echo para executar
            echo "cp \"$file\" \"${destination_path}${only_dirname}_${only_filename}\""
        fi
    done
}

# pasta de destino (troque pela pasta de destino, caminho completo)
destination_path="/home/destination/"

# pasta aonde estão as fotos (troque pelo caminho completo desejado)
source_path="/home/bar/"

move_recursive $source_path

Swapping blanks for underline/underscore with bash

I couldn’t test because my system isn’t Unix-like, so I can’t say if it works, but I think if I use it this way:

echo "cp \"$file\" \"${destination_path}${only_dirname//[[:blank:]]/_}_${only_filename//[[:blank:]]/_}\""

All spaces will be exchanged for _, in a practical example, it would be this:

#!/bin/bash

foo="a b c d"

echo ${foo//[[:blank:]]/_}

Being [[:blank:]] regular expression for white spaces (Tabs too) and after the / would be the character that will replace.

  • 1

    The function worked perfectly. I liked the idea of using echo to show the commands that will be executed. I’ve never seen this before.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.