Eu inventei isso, mas infelizmente isso não afeta nenhum arquivo/pasta em subpastas.
find . -exec rename "s/^\s+//" {} \;
Estrutura de pastas:
foo
|-- \ bar
`-- \ foo1
|-- \ bar1
`-- \ foo2
`-- \ bar2
Responder1
A renomeação precisa ser feita de baixo para cima
O problema é que você precisa renomear os diretóriosde baixo para cima. Caso contrário, o comando tentará renomear arquivos e diretórios que estão dentro de pastas já movidas (renomeadas) e, portanto, não poderá mais encontrá-los.
É aqui que python
's os.walk()
pode ser usado, em combinação comtopdown=False
Em um pequeno script:
#!/usr/bin/env python3
import os
import shutil
import sys
for root, dirs, files in os.walk(sys.argv[1], topdown=False):
for f in files:
if f.startswith(" "):
shutil.move(root+"/"+f, root+"/"+f.strip())
for dr in dirs:
if dr.startswith(" "):
shutil.move(root+"/"+dr, root+"/"+dr.strip())
Usar
- Copie o script em um arquivo vazio e salve-o como
no_space.py
Execute-o pelo comando:
python3 /path/to/no_space.py /path/to/directory/to/rename
Responder2
Conforme observado em outras respostas, a questão principal é o que ^
ancora o início docaminho, em vez do início do nome do arquivo. Existem várias maneiras de contornar isso com find
and rename
: provavelmente o mais seguro seria usar -execdir
no lugar de -exec
para que todos os componentes do caminho reduzam para ./
e depois substituam o padrão\./\s+
Além disso, se você estiver renomeando diretóriospossivelmente incluindo ancestrais de outros arquivos/diretórios que serão renomeados, então você deve fazer uma travessia em profundidade.
Juntar as peças,
find . -depth -name ' *' -execdir rename -vn -- 's#\./\s+##' {} +
ou (funcionalmente equivalente, mas um pouco mais fácil de ver o que está acontecendo) usando um "olhar atrás" de comprimento zero para o separador de caminho
$ find . -depth -name ' *' -execdir rename -vn -- 's#(?<=\./)\s+##' {} +
./ bar2 renamed as ./bar2
./ foo2 renamed as ./foo2
./ bar1 renamed as ./bar1
./ foo1 renamed as ./foo1
./ bar renamed as ./bar
[NOTA: remova -n
quando tiver certeza de que faz o que deseja]
Responder3
Acho que o problema está no formato de saída do find, que inclui o caminho completo. Então para bar2 você terá
./ foo1/ foo2 /bar2
essa renomeação não será entendida corretamente.
Uma solução é usar um script para fazer cada pasta recursivamente assim:
#!/bin/bash
# if argument given consider it is the directory to parse
if [ -n "$1" ]; then
cd "$1"
fi
# rename all files in current folder
find . -maxdepth 1 -printf '%f\0' | xargs -0r -n 1 rename -nono 's/^\s+//'
# No, repeat for all subfolders with current script (we are in the subfolder)
find . -maxdepth 1 -type d -not -name '.' -print0 | xargs -0r -n 1 "$(readlink -f $0)"