2009-05-06 9 views
2

Vous essayez de renommer une série de fichiers sur un serveur Linux. Trouver les fichiers que je veux est facile:Renommer une série de fichiers

find . -type f -wholename \*.mbox 

Bien sûr, étant des fichiers mbox, certains d'entre eux ont des espaces dans les noms, il devient:

find . -type f -wholename \*.mbox -print0 

Je suis conduite à xargs de telle sorte que Je peux renommer les fichiers:

find . -type f -wholename \*.mbox -print0 | xargs -0 -I{} echo ${"{}"/.mbox/} 

L'écho devrait retourner quelque chose comme INBOX, étant donné INBOX.mbox, cependant, bash se plaint:

bash: ${"{}"/.mbox/}: bad substitution 

Comment puis-je résoudre ce problème? Je voudrais essayer de le garder dans une solution find/xargs si possible, de sorte que je n'ajoute pas beaucoup de constructions en boucle autour d'elle.

Répondre

8

Essayez

find . -type f -wholename \*.mbox | sed 's/\(.*\)\.mbox/mv "\1.mbox" "\1"/' | sh 

Ce n'est pas 100% indéréglable devrait certains fichiers contiennent des caractères à double citation, mais je suppose vous pouvez ignorer :)

+0

Un avantage supplémentaire à cette solution est que si vous laissez le '' | sh' à la fin vous obtenez une liste de commandes qui seront exécutées. Si tout a l'air ok, vous pouvez ensuite le rediriger vers le shell à exécuter. –

+0

Oui, bon point. Je redirige toujours vers moins pour voir si les commandes sont sensées lors de l'exécution de commandes de cette façon. – hlovdal

+0

J'ai remarqué que la tuyauterie droite vers une coque comme montré est également supérieure à l'utilisation de xargs car elle gère intuitivement les citations, elle est également susceptible d'offrir de meilleures performances. Merci @hlovdal – rupert160

1

Vous pouvez essayer:

find . -type f -wholename \*.mbox -print0 | sed 's/\.mbox//' 

Votre problème est en essayant de tuyau dans xargs. Par ce point "{}" ne veut rien dire.

Pour renommer les fichiers (si vous êtes sous bash)

find . -type f -wholename \*.mbox -print0 | \ 
    while read I ; do 
     mv $I $(echo $I | sed 's/\.mbox//') ; 
    done ; 
+0

Comment cela m'aidera-t-il à renommer le fichier? –

+0

édité la réponse pour répondre à vos besoins – dsm

1

Je pense que vous devez ceci:

find . -wholename \*.mbox | awk '{new=$0; gsub("\.mbox$", "", new) ; system("mv \"" $0 "\" \"" new "\"") }' 

(devrait être à la fois compatible gawk et mawk, testé sur mawk). Il n'utilise pas xargs, mais notez qu'il n'entraîne pas un nouveau processus pour chaque fichier déplacé. Si vous devez déplacer une grande quantité de fichiers, vous remarquerez l'avantage. Warrning: si l'un des fichiers contient une nouvelle ligne dans son nom, vous aurez des ennuis (mais si c'est un problème, Dieu soit avec vous).

Vous améliorez encore cette solution en utilisant xargs pour supprimer plusieurs fichiers sur une seule invocation rm.

Si vous avez vraiment besoin de vitesse, je vous suggère d'utiliser un script python au lieu de awk. Cela fera tous les rm sans une seule fourchette.

1

Pourriez-vous utiliser rename (1)? Il vient avec Perl.

0

Ici, vous allez, cela devrait faire l'affaire ....

# find . 
. 
./test.tst 
./test1.tst 
./test2.tst 
./test/test4.tst 
./test/test5.tst 

# 

for file in `find . -type f` 
do 
mv $file ${file%.tst}.new 
done 

# find . 
. 
./test 
./test/test4.new 
./test/test5.new 
./test1.new 
./test2.new 
+0

cette solution est sujette à des erreurs lorsque les fichiers ont des espaces en eux. – ghostdog74

2

GNU Parallel http://www.gnu.org/software/parallel/ a qui supprime l'extension {.}:

find . -type f -wholename \*.mbox -print0 | parallel -0 mv {} {.} 

Si vous connaissez les noms de fichiers ne pas contient \ n alors cela fonctionnera aussi:

find . -type f -wholename \*.mbox | parallel mv {} {.} 
+0

juste ce que je cherchais. Merci. et merci pour parallèle –