Adicione o nome da pasta a todos os arquivos '.bin' nessa pasta

1

Eu passei quase um dia e meio procurando por isso, mas não consegui encontrar uma resposta.

Eu estou olhando para adicionar o nome da pasta como um prefixo para todos os arquivos que terminam com .bin nessa pasta.

Portanto, se o nome da pasta for ABC e contiver os arquivos aa.bin , bb.bin , cc.bin etc., será necessário que eles sejam renomeados como ABC-aa.bin , ABC-bb.bin , ABC-cc.bin , etc.

Além disso, esta pasta ABC tem subpastas, vamos chamá-las: ABC1 , ABC2 , ABC3 , etc., que também têm .bin arquivos. Por exemplo, ABC1 tem aa1.bin , bb1.bin , cc1.bin , etc.

Eu preciso desse comando para passar por todas as pastas e acrescentar o nome da subpasta aos arquivos dentro dela também. Então, aa1.bin será ABC1-aa1.bin e assim por diante.

Estrutura de diretórios:

.
└── ABC
    ├── aa.bin
    ├── ABC1
    │   ├── aa1.bin
    │   └── bb1.bin
    ├── ABC2
    │   ├── aa2.bin
    │   └── bb2.bin
    ├── bb.bin
    └── cc.bin
    
por Krishna 08.02.2016 / 17:05

3 respostas

1

Aqui está um "one-liner" para fazer, usando os built-ins do shell para manipular os nomes dos arquivos:

find . -name '*.bin' -exec sh -c 'p="${1%/*}"; f="${1##*/}"; echo mv -- "" "$p/${p##*/}-$f"' sh {} \;

Teste-o no diretório de destino e remova o echo se os resultados parecerem corretos

por exemplo. dado

$ tree .
.
└── ABC
    ├── aa.bin
    ├── ABC1
    │   ├── aa1.bin
    │   └── bb1.bin
    ├── ABC2
    │   ├── aa2.bin
    │   └── bb2.bin
    ├── bb.bin
    └── cc.bin

3 directories, 7 files

então

$ find . -name '*.bin' -exec sh -c 'p="${1%/*}"; f="${1##*/}"; echo mv -- "" "$p/${p##*/}-$f"' sh {} \;
mv -- ./ABC/ABC2/bb2.bin ./ABC/ABC2/ABC2-bb2.bin
mv -- ./ABC/ABC2/aa2.bin ./ABC/ABC2/ABC2-aa2.bin
mv -- ./ABC/aa.bin ./ABC/ABC-aa.bin
mv -- ./ABC/bb.bin ./ABC/ABC-bb.bin
mv -- ./ABC/ABC1/bb1.bin ./ABC/ABC1/ABC1-bb1.bin
mv -- ./ABC/ABC1/aa1.bin ./ABC/ABC1/ABC1-aa1.bin
mv -- ./ABC/cc.bin ./ABC/ABC-cc.bin

parece ser bom, remova o echo e execute-o novamente

$ find . -name '*.bin' -exec sh -c 'p="${1%/*}"; f="${1##*/}"; mv -- "" "$p/${p##*/}-$f"' sh {} \;

dando

$ tree .
.
└── ABC
    ├── ABC1
    │   ├── ABC1-aa1.bin
    │   └── ABC1-bb1.bin
    ├── ABC2
    │   ├── ABC2-aa2.bin
    │   └── ABC2-bb2.bin
    ├── ABC-aa.bin
    ├── ABC-bb.bin
    └── ABC-cc.bin

3 directories, 7 files
    
por steeldriver 08.02.2016 / 18:26
1

Você pode fazer isso usando os comandos find , basename , dirname e mv . Por exemplo, como neste script simples:

#!/bin/bash

for f in $(find ABC -name '*.bin'); 
do 
  filename="$(basename $f)" 
  dir="$(dirname $f)"
  lastdir="$(basename $dir)"
  newname="$lastdir-$filename"
  newpath="$dir/$newname"
  mv $f $newpath
done

Aqui estou usando o find para encontrar recursivamente todos os arquivos .bin no ABC, depois iterar sobre eles e extrair o último nome da pasta. Em seguida, o novo caminho é construído e o arquivo é movido para o mesmo diretório, mas com o novo nome.

Editar :
Para executar este script copie seu conteúdo para algum arquivo. Digamos que o nome do arquivo seja renameFiles.sh . Em seguida, torne-o executável:

chmod +x renameFiles.sh

Depois disso, você pode executá-lo com ./renameFiles.sh . Observe que a pasta onde você colocou esse arquivo deve ser a mesma onde sua pasta ABC está localizada.

renameFiles.sh
ABC
  aa.bin
  bb.bin
  ABC1
    aa1.bin
    etc.
    
por incBrain 08.02.2016 / 18:07
0

Usando rename :

shopt -s globstar
rename -n '(! -f $_ || ! /.bin$/) && next; $" = "/"; my @f = split("/"); $f[@f-1] =~ s/^/$f[@f-2]-/; $_ = "@f"' **
  • shopt -s globstar : Se definido, o padrão '**' usado em um contexto de expansão de nome de arquivo corresponderá a todos os arquivos e zero ou mais diretórios e subdiretórios. Se o padrão for seguido por um '/', apenas diretórios e subdiretórios serão correspondentes.
  • rename -n '! -f $_ && next; $" = "/"; my @f = split("/"); $f[@f-1] =~ s/^/$f[@f-2]-/; $_ = "@f"' ** : executa uma execução a seco do seguinte. Para cada nome de arquivo resultante da ** globbing: se o arquivo não for um arquivo normal ou o nome do arquivo não terminar com .bin , pulará para o próximo nome de arquivo; define o separador do campo de saída como / ; divide o nome do arquivo em / ; precede o segundo ao último campo seguido por - para o último campo; atribui o novo nome do arquivo à variável padrão ( $_ ).

Se o resultado for o esperado, remova a opção -n do comando rename .

$ tree
.
└── ABC
    ├── aa.bin
    ├── ABC1
    │   ├── aa1.bin
    │   └── bb1.bin
    ├── ABC2
    │   ├── aa2.bin
    │   └── bb2.bin
    ├── bb.bin
    └── cc.bin

3 directories, 7 files
$ rename -n '(! -f $_ || ! /.bin$/) && next; $" = "/"; my @f = split("/"); $f[@f-1] =~ s/^/$f[@f-2]-/; $_ = "@f"' **
Exiting subroutine via next at (eval 4) line 1.
rename(ABC/aa.bin, ABC/ABC-aa.bin)
Exiting subroutine via next at (eval 4) line 1.
rename(ABC/ABC1/aa1.bin, ABC/ABC1/ABC1-aa1.bin)
rename(ABC/ABC1/bb1.bin, ABC/ABC1/ABC1-bb1.bin)
Exiting subroutine via next at (eval 4) line 1.
rename(ABC/ABC2/aa2.bin, ABC/ABC2/ABC2-aa2.bin)
rename(ABC/ABC2/bb2.bin, ABC/ABC2/ABC2-bb2.bin)
rename(ABC/bb.bin, ABC/ABC-bb.bin)
rename(ABC/cc.bin, ABC/ABC-cc.bin)
    
por kos 08.02.2016 / 19:24