Batch renommer les files qui se terminent par un point

J'ai un grand server de files Unix, avec un seul grand partage SMB. Il sert aux clients Mac, Linux et Windows. Une grande partie des files sur cette boîte ont été migrés depuis un Mac Xserve. L'une des façons dont le partage est sauvegardé est via une boîte Windows. Ce logiciel de sauvegarde particulier échoue si il existe des caractères qu'il n'aime pas dans les noms de files.

J'ai réussi à réparer la plupart des problèmes de nom de file, mais je me heurte à des files qui se terminent par un point. Par exemple:

  • filename.
  • newfile.txt.
  • stupid old file.

J'essaie de find un moyen de renommer tous les files qui se terminent par un point portant le même nom sans le point. Donc, filename. devient filename

 find . -name "*." 

travaille à find les files. J'ai essayé de le faire passer par sed:

 find . -name "*." | sed 's/.$//' 

qui fait le travail dans la console mais ne renvoie pas les files. C'est la partie avec laquelle je me débat.

Si vous avez la version de script Perl de rename (appelée rename ou prename ):

 rename 's/\.$//' *. 

ou la version util-linux (appelée rename ou rename-ul ):

  rename . '' *. 

Si vous exécutez la command sans arguments et obtenez quelque chose de similaire à:

Utilisation: renommer [-v] [-n] [-f] perlexpr [noms de files]

alors c'est la version de script Perl.

Quelque chose comme:

renommer.ul: pas assez d'arguments

Utilisation: rename.ul [options] file de rlocation d'expression …

Options: -v, -verbose explique ce qui se fait -V, –version
publiez les informations de la version et quittez -h, – aidez cette aide et quittez

signifie que c'est la version util-linux.

Un peu méchant mais devrait fonctionner:

Si vous souhaitez renommer les files ET les directorys avec les points de départ:

  find . -name "*." -print0 | xargs -0 -n 1 my_rename.sh 

OU si vous souhaitez renommer uniquement les files:

  find . -name "*." -type f -print0 | xargs -0 -n 1 my_rename.sh 

Où le script my_rename.sh est juste:

 #!/bin/bash mv "$1" "${1%%.}" 

(N'oubliez pas non plus de rendre exécutable le script: chmod +x my_rename.sh ) 2

Cela ressemble à ce qu'il devrait faire le travail:

find . -type f -name '*\.' -exec bash -c 'mv "$1" "${$1%.}"' _ {} \;

Cela limite la search à des files uniquement avec une période à la fin (sinon, il correspond au directory de travail actuel, '.'), Puis exécute l'extrait de shell cité ( mv "$1" "${$1%.}" ) Pour chaque nom de file qu'il trouve. Dans l'extrait de shell, il utilise l'expansion et la substitution des parameters bash pour supprimer le '' '. L'autre bruit de ligne à la fin est nécessaire pour find -exec: {} est le text correspondant de la search, \; est nécessaire pour terminer la string exec, et je crois que le _ indique à l'exec de passer {} dans comme paramètre ( $1 ) à la command sh . Pour être honnête, cette utilisation spécifique de -exec est nouvelle pour moi, je l'ai trouvé ici .

Le bit de substitution bash est très simple, et je l'utilise assez souvent pour renommer les files, par exemple, FILENAME=foo.JPG; mv ${FILENAME} ${FILENAME%.JPG}.jpg FILENAME=foo.JPG; mv ${FILENAME} ${FILENAME%.JPG}.jpg supprime le '.JPG' de FILENAME et le remplace par '.jpg'

Si vous souhaitez toujours utiliser l'expansion sed plutôt que bash, cela semble qu'il ferait le travail:

 find . -type f -name '*\.' -exec sh -c 'mv "{}" "$(echo {} | sed s/\.$// )"' \; 

J'ai d'abord essayé de résoudre ceci sans provoquer -exec pour invoquer sh -c , mais cela n'a pas aimé étendre {} dehors en essayant de faire le sed (ou avec l'exemple de substitution bash plus tôt).

Notez également que vous devez mettre "" autour des noms de files que vous développez (par exemple, {} ou $ 1, selon l'exemple), car vos exemples de files ont des espaces dans ceux-ci. Cela peut encore se briser en fonction de ce que les caractères spéciaux sont dans votre file (par exemple, un "dans le nom de file peut causer des problèmes).