Primeiro de tudo, aqui está a árvore de exemplo que criei:
{ pwd
for d in ./*/
do cd "$d"
printf '\t%s\n' "${d#??}"
printf '\t\t%s\n' *
cd ..
done
}
/tmp/top
another file/
another file.pdf
fileA/
fileA.pdf
otherdir/
1
2
3
stillanother4544file/
stillanother4544file.pdf
Agora, obviamente, você não precisa fazer nada disso - criei a árvore para espelhar sua árvore de exemplo e adicionei alguns valores discrepantes.
Mas aqui está o que eu recomendo que você faça:
pax -rwis'|^./\([^/]*\)/\(\....\)$||' -s'|.*||' . ../tgt
Chama o utilitário pax
padrão POSIX no modo -r
ead / -w
rite - modo cópia direta, basicamente. No modo de cópia pax
não cria um tar
archive como usualmente faria no modo -w
rite, mas copia diretamente todos os arquivos encontrados em seu [...pattern...]
argumento [s] - que está aqui apenas .
para a árvore com raiz no diretório atual - e / ou os nomes dos quais ele lê em seu stdin - que está vazio neste caso - para o diretório nomeado como seu último argumento - que está aqui ../tgt
.
Agora, eu sei, você não quer mover a árvore inteira. Muito disso é tratado com os argumentos -s
ubstitution. Você pode renomear os arquivos de saída com base na expressão regular sed
-style declarações como eu faço aqui. Eu uso duas declarações -s
ubstitution. O primeiro renomeia todas as correspondências de entrada para:
./dirname/samename.???
... para ...
samename.???
... na saída, achatando a árvore de saída para colocar todos os arquivos copiados em ../tgt
diretamente. Se preferir manter os diretórios ./dirname/
parent para cada um, você pode substituir a parte da primeira
-s
ubstitution por apenas &
.
Depois que um nome de arquivo for correspondido e modificado com êxito por pax
-s
ubstitution, ele não será tentado novamente por nenhum argumento -s
ubstitution restante e apenas os arquivos que ainda não foram correspondidos serão tentados para qualquer renomeação restante expressões regulares. Isso significa que todos os arquivos com raiz no diretório atual com nomes de caminho que se ajustam ao tipo:
./dirname/samename.???
... são selecionados e despojados com sucesso de todos, exceto de seus últimos componentes de nome de caminho com a primeira instrução -s
ubstitution e todos os arquivos outros com raiz no diretório atual são substituídos completamente pelo segundo -s|.*||
-s
ubstitution. Isso ocorre porque pax
descarta de sua lista de processamento qualquer nome de arquivo que substitua uma cadeia nula.
Uma vez pax
processou tudo o que tem um último dever a cumprir antes de poder realmente copiar os arquivos selecionados - e essa é a opção -i
nteractive rename que eu especifiquei, e que eu acho que provavelmente está certa seu beco.
De man pax
:
-i
- Interactively rename files or archive members. For each archive member matching a
pattern
operand or each file matching a file operand,pax
will prompt to/dev/tty
giving the name of the file, its file mode, and its modification time.pax
will then read a line from/dev/tty
. If this line is blank, the file or archive member is skipped. If this line consists of a single period, the file or archive member is processed with no modification to its name. Otherwise, its name is replaced with the contents of the line.pax
will immediately exit with a non-zero exit status ifEOF
is encountered when reading a response or if/dev/tty
cannot be opened for reading and writing.
ATTENTION: pax interactive file rename operation.
-rw-r--r-- Oct 17 04:30 stillanother4544file.pdf
Input new name, or a "." to keep the old name, or a "return" to skip this file.
Input > .
Processing continues, name unchanged.
ATTENTION: pax interactive file rename operation.
-rw-r--r-- Oct 17 04:30 another file.pdf
Input new name, or a "." to keep the old name, or a "return" to skip this file.
Input >
Skipping file.
ATTENTION: pax interactive file rename operation.
-rw-r--r-- Oct 17 04:30 fileA.pdf
Input new name, or a "." to keep the old name, or a "return" to skip this file.
Input > .
Processing continues, name unchanged.
Assim, dos seis arquivos no diretório atual, apenas os três passam para os prompts de renomeação -i
nteractive e, desses três, apenas dois chegam a ../tgt
:
ls -l ../tgt
-rw-r--r-- 1 mikeserv mikeserv 0 Oct 17 04:30 fileA.pdf
-rw-r--r-- 1 mikeserv mikeserv 0 Oct 17 04:30 stillanother4544file.pdf