Copy batch files, renaming them with the original directory name

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

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

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 the source directories.

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

    
asked by anonymous 22.07.2018 / 18:54

1 answer

2

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

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

The "function" inside bash could get something like move_recursive , so with the command cp it will move the file to the desired destination (you can change to mv if you want to move at once, which does not I recommend because the script was not 100% tested), then this:

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

It 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 it did this $only_dirname_$only_filename would fail.

  

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

To get just 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

Exchanging blanks for underline / underscore with bash

I have not been able to test because my system is not unix-like, so I can not tell if it works, but I think using it this way:

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

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

#!/bin/bash

foo="a b c d"

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

Being [[:blank:]] the regular expression for whitespace (TABs too) and after / would be the character it will replace.

    
22.07.2018 / 20:09