Antes de declarar isso como uma duplicata, considere que eu precisaria disso por um motivo específico: renomear em lote (ou copiar para um novo nome) de uma estrutura em árvore que contenha uma cadeia comum em nomes de arquivos e diretórios. Aqui está um exemplo (tentei no Ubuntu 14.04, então ferramentas GNU):
cd /tmp
mkdir myproj
mkdir -p myproj/myproj_AA/myproj_BB
touch myproj/myproj_AA/myproj_BB/myproj_CC.dat
mkdir myproj/myproj_AA/myproj_DD
touch myproj/myproj_AA/myproj_DD/myproj_EE.dat
mkdir -p myproj/myproj_XX/myproj_YY
touch myproj/myproj_XX/myproj_YY/myproj_ZZ.dat
mkdir -p myproj/myproj_XX/myproj_WW
touch myproj/myproj_XX/myproj_WW/myproj_QQ.dat
tree myproj # to visualise
Esta estrutura de diretórios tree
se parece com isso:
myproj
├── myproj_AA
│ ├── myproj_BB
│ │ └── myproj_CC.dat
│ └── myproj_DD
│ └── myproj_EE.dat
└── myproj_XX
├── myproj_WW
│ └── myproj_QQ.dat
└── myproj_YY
└── myproj_ZZ.dat
6 directories, 4 files
Então, eu gostaria que todas as entradas em myproj/
, incluindo myproj
, fossem renomeadas para myTESTproj
em vez de myproj
(onde quer que isso possa ocorrer como um nome). Então, primeiro eu preciso obter uma listagem com caminhos relativos em relação ao diretório atual - e então eu preciso tê-lo classificado de tal forma que os filhos externos (eu acho que isso é equivalente a arquivos com os nomes de caminhos relativos mais longos, mas não tenho certeza) são os primeiros (porque se eu renomear / mv o diretório primeiro e, em seguida, tentar renomear um arquivo nele, ele provavelmente usará o antigo nome do dir como primeiro argumento e falhará, pois o nome agora é alterado).
Estou ciente de que há ls -R --group-directories-first myproj/
para usar ls
recursivamente e diretórios de grupos primeiro, mas sua saída é assim:
$ ls -R --group-directories-first myproj/
myproj/:
myproj_AA myproj_XX
myproj/myproj_AA:
myproj_BB myproj_DD
myproj/myproj_AA/myproj_BB:
myproj_CC.dat
myproj/myproj_AA/myproj_DD:
myproj_EE.dat
myproj/myproj_XX:
myproj_WW myproj_YY
myproj/myproj_XX/myproj_WW:
myproj_QQ.dat
myproj/myproj_XX/myproj_YY:
myproj_ZZ.dat
... ou seja, não é uma lista simples com subcaminhos, que eu poderia facilmente alimentar a while read f; do ...
O mais próximo que cheguei foi usar find
:
$ find myproj/
myproj/
myproj/myproj_AA
myproj/myproj_AA/myproj_DD
myproj/myproj_AA/myproj_DD/myproj_EE.dat
myproj/myproj_AA/myproj_BB
myproj/myproj_AA/myproj_BB/myproj_CC.dat
myproj/myproj_XX
myproj/myproj_XX/myproj_YY
myproj/myproj_XX/myproj_YY/myproj_ZZ.dat
myproj/myproj_XX/myproj_WW
myproj/myproj_XX/myproj_WW/myproj_QQ.dat
Então, aqui eu tenho uma lista simples de subcaminhos, no entanto, ele é classificado primeiro no nó raiz em direção aos nós folha - e eu preciso dos nós folha primeiro. E estou tentando coisas como find myproj/ | sort -n
, mas parece não fazer diferença. Então, se eu fizer algo como:
$ find myproj/ | sort -n | while read f; do mv -v $f $(echo $f | sed 's/myproj/myTESTproj/g'); done
‘myproj/’ -> ‘myTESTproj/’
mv: cannot stat ‘myproj/myproj_AA’: No such file or directory
mv: cannot stat ‘myproj/myproj_AA/myproj_BB’: No such file or directory
mv: cannot stat ‘myproj/myproj_AA/myproj_BB/myproj_CC.dat’: No such file or directory
...
... então a renomeação recursiva pretendida falha imediatamente, pois o nó raiz (diretório) é renomeado primeiro e, portanto, todas as outras referências a ele são inválidas.
Então, como posso obter uma listagem recursiva apropriada de um subdiretório com nós de folha primeiro, para usá-lo em uma renomeação em lote como essa?