Je suis venu avec cela, mais malheureusement, cela n’affecte pas les fichiers/dossiers des sous-dossiers.
find . -exec rename "s/^\s+//" {} \;
Structure du dossier:
foo
|-- \ bar
`-- \ foo1
|-- \ bar1
`-- \ foo2
`-- \ bar2
Le problème est que vous devez renommer les répertoires de bas en haut. Sinon, la commande essaiera de renommer les fichiers et les répertoires qui se trouvent dans des dossiers déjà déplacés (renommés) et ne les trouvera donc plus.
C’est ici que vous pouvez utiliser os.walk()
de python
, en combinaison avec topdown=False
Dans un petit 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())
no_space.py
Exécutez-le à l'aide de la commande:
python3 /path/to/no_space.py /path/to/directory/to/rename
Comme indiqué dans d'autres réponses, le problème principal est que ^
ancre le début du chemin plutôt que le début du nom de fichier. Il existe plusieurs façons de contourner ce problème avec find
et rename
: le plus sûr serait probablement d'utiliser -execdir
à la place de -exec
de sorte que tous les composants de chemin soient réduits à ./
, puis remplacez le motif \./\s+
De même, si vous renommez des répertoires en incluant éventuellement les ancêtres d'autres fichiers/répertoires à renommer, vous devez effectuer une traversée en profondeur d'abord.
Mettre ensemble,
find . -depth -name ' *' -execdir rename -vn -- 's#\./\s+##' {} +
ou (fonctionnellement équivalent, mais un peu plus facile à voir ce qui se passe) en utilisant une "longueur nulle" pour le séparateur de chemin
$ 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
[NOTE: retirez le -n
une fois que vous êtes sûr qu'il fait ce que vous voulez]
Je pense que le problème est avec le format de sortie de find, qui inclut le chemin complet. Donc pour bar2 vous aurez
./ foo1/ foo2 /bar2
ce renommage ne comprendra pas correctement.
Une solution consiste à utiliser un script pour faire chaque dossier de manière récursive comme ceci:
#!/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)"