Existem várias ferramentas de cópia de arquivos que permitem construir um nome de diretório de destino com regras suficientemente flexíveis ( zcp
, rsync
, pax
,…). Infelizmente, poucos deles permitem tanto mover (ao contrário de copiar) e criar diretórios de destino sob demanda. Então, mostrarei algumas maneiras de fazer isso em duas etapas: primeiro crie todos os diretórios de destino potencialmente necessários e, em seguida, execute a movimentação.
Renomear Perl
O programa Perl rename
fornecido pela Debian e pelo Ubuntu pode criar o diretório de destino quando necessário, se você escrever o bit de Perl necessário.
shopt -s globstar # make **/ traverse directories recursively (requires bash 4)
rename 'BEGIN {use File::Path}
s!^/data!/raw_data!;
m!(.*)/!; mkpath($1)' /data/**/*.raw
Em zsh, omita a linha shopt -s globstar
; **
significa percurso recursivo por padrão. Em shells diferentes de bash e zsh, você precisa usar find
para travessias recursivas (veja os exemplos abaixo). Não se preocupe com tudo isso se você tiver um único nível de diretórios.
Criando os diretórios de destino
Em zsh (explicação: o qualificador de glob /
significa corresponder apenas diretórios e o qualificador e
glob aplica a transformação fornecida posteriormente a cada nome):
mkdir /data/**/*(/e\''REPLY=${REPLY/data/raw_data}'\')
Com outros shells:
find /data -type d \
-exec sh -c 'for d; do mkdir "/raw_data${d#/data}"; done' _ {} +
Se você tiver apenas um nível de subdiretórios, é muito mais simples:
for d in /data/*/; do mkdir "/raw_data${d#/data}"; done
Movendo os arquivos (zsh)
autoload zmv
zmv -Q '/data/(**/)(*.raw)(.)' '/raw_data/$1$2'
Movendo os arquivos (portáteis)
find /data -name '*.raw' \
-exec sh -c 'for x; do mv "$x" "/raw_data${x#/data}"; done' _ {} +