Tenta aprender sobre o shell script

1

Eu tento aprender uma nova habilidade para shell script. Então agora eu recebo uma lição do meu professor sobre mover o arquivo para um novo diretório.

Pergunta

Existe um padrão de arquivo

A_20180423_0015  B_20180501_0045  C_20180426_0045  

e deseja mover arquivos para esses diretórios como / new / destpath / A / 20180423 / 0015,0030,0045 cada diretório tem 3 arquivos

no meu script eu escrevo

 #! /bin/bash
cd /app/Moving/DEST_PATH
mkdir A B C D
cd /app/Moving/DEST_PATH/A
MakesubA=$(for itype in A;do for ((i=1;i<=10;i++));do for ((itime=15;itime<=45;itime=itime+15));do mkdir ${itype}_$(date --date "${i} day ago" +"%Y%m%d")_00${itime} ;done;done;done)
cd ..
cd /app/Moving/DEST_PATH/B
MakesubB=$(for itype in B;do for ((i=1;i<=10;i++));do for ((itime=15;itime<=45;itime=itime+15));do mkdir ${itype}_$(date --date "${i} day ago" +"%Y%m%d")_00${itime} ;done;done;done)
cd ..
cd /app/Moving/DEST_PATH/C
MakesubC=$(for itype in C;do for ((i=1;i<=10;i++));do for ((itime=15;itime<=45;itime=itime+15));do mkdir ${itype}_$(date --date "${i} day ago" +"%Y%m%d")_00${itime} ;done;done;done)
cd ..
cd /app/Moving/DEST_PATH/D
MakesubD=$(for itype in D;do for ((i=1;i<=10;i++));do for ((itime=15;itime<=45;itime=itime+15));do mkdir ${itype}_$(date --date "${i} day ago" +"%Y%m%d")_00${itime} ;done;done;done)
cd ..

e eu tento descobrir isso para usar o loop ou outra coisa, mas eu não sei qual o uso para selecionar cada arquivo para cada diretório.

    
por Dnop 04.05.2018 / 06:11

1 resposta

2

Você tem arquivos que basicamente têm um caminho de destino codificado em seus nomes de arquivos.

O arquivo chamado A_20180423_0015 deve ser movido para A/20180423/0015 (suponho que 0015 é o novo nome do arquivo no diretório A/20180423 ), que é um nome de caminho que é o mesmo que o original nome do arquivo, mas com os sublinhados substituídos por barras.

Isso significa que este exercício é sobre a substituição de caracteres em strings.

Não há necessidade de passar e criar diretórios de destino para cada data possível, porque o destino já está codificado no nome do arquivo dos arquivos.

Não tenho certeza absoluta de onde os arquivos originais estão localizados, ou se você pode usar apenas [A-Z]_*_* como um padrão para combiná-los no diretório atual (vou assumir que você pode).

for source_filename in [A-Z]_*_*; do
    target_pathname=${source_filename//_//}
    mkdir -p "${target_pathname%/*}"
    mv "$source_filename" "$target_pathname"
done

Se começarmos com

.
|-- A_20180423_0015
|-- B_20180501_0045
'-- C_20180426_0045

0 directory, 3 files

... e execute o código acima, depois terminaremos com

.
|-- A/
|   '-- 20180423/
|       '-- 0015
|-- B/
|   '-- 20180501/
|       '-- 0045
'-- C/
    '-- 20180426/
        '-- 0045

6 directories, 3 files

Código anotado:

# Loop over all names in the current directory that matches the given pattern.
for source_filename in [A-Z]_*_*; do
    # Replace all underscores in the found name with slashes.
    # We use bash's ${parameter//pattern/replacement} pattern substitution
    # to do this.
    # If you need to append a path to this, just do so with
    #    target_pathname="/some/path/${source_filename//_//}"
    target_pathname=${source_filename//_//}

    # Make sure that the target directory exists.
    # With ${target_pathname%/*} we remove the filename component of
    # the target pathname to get the directory of the destination file.
    # You may change this to the following if you wish:
    #     mkdir -p "$( dirname "$target_pathname" )"
    mkdir -p "${target_pathname%/*}"

    # Move the file into place.
    mv "$source_filename" "$target_pathname"
done

Se eu entendi mal a questão e os arquivos devem manter seus nomes de arquivo originais, mas sejam movidos para diretórios correspondentes ao nome do arquivo, ou seja, A_20180423_0015 deve ser movido para A/20180423/0015/A_20180423_0015 , só precisamos alterar alguns caracteres o código acima:

mkdir -p "${target_pathname%/*}"

muda para

mkdir -p "$target_pathname"

Essa mudança nos daria

.
|-- A/
|   '-- 20180423/
|       '-- 0015/
|           '-- A_20180423_0015
|-- B/
|   '-- 20180501/
|       '-- 0045/
|           '-- B_20180501_0045
'-- C/
    '-- 20180426/
        '-- 0045/
            '-- C_20180426_0045

9 directories, 3 files

Para o caso em que os arquivos de origem estão localizados em outro diretório que não o atual:

for source_pathname in /some/source/path/[A-Z]_*_*; do
    source_filename=${source_pathname##*/}
    target_pathname="some/target/path/${source_filename//_//}"
    mkdir -p "$target_pathname"
    mv "$source_pathname" "$target_pathname"
done
    
por 04.05.2018 / 08:31