Je veux renommer des fichiers pour changer leur extension, en cherchant efficacement à accomplir
mv *.txt *.tsv
Mais en faisant cela, je reçois:
* .tsv n'est pas un répertoire
Je trouve un peu étrange que les 10 premiers résultats de Google mv
soient affichés comme ça.
Réponses:
Lorsque vous exécutez la commande:
le shell, supposons bash, développe les caractères génériques s'il y a des fichiers correspondants (y compris des répertoires). La liste des fichiers est passée au programme, ici
mv
. Si aucune correspondance n'est trouvée, la version non étendue est transmise.Encore une fois: le shell étend les motifs, pas le programme.
Beaucoup d'exemples est peut-être le meilleur moyen, alors c'est parti:
Exemple 1:
Maintenant, ce qui se passe sur la
mv
ligne, c'est que le shell se développe*.txt
dans les fichiers correspondants. Comme il n'y a aucun*.tsv
fichier qui n'est pas modifié.La
mv
commande est appelée avec deux arguments spéciaux :argc
: Nombre d'arguments, y compris le programme.argv
: Un tableau d'arguments, y compris le programme comme première entrée.Dans l'exemple ci-dessus, ce serait:
Le
mv
programme vérifie si le dernier argument,,*.tsv
est un répertoire. Comme il ne l'est pas, le programme ne peut pas continuer car il n'est pas conçu pour concaténer des fichiers. (Déplacez généralement tous les fichiers en un seul.) Ni créez de répertoires sur un coup de tête.En conséquence, il abandonne et signale l'erreur:
Exemple 2:
Maintenant, si vous dites à la place:
La
mv
commande est exécutée avec:Maintenant, encore une fois,
mv
vérifiez s'il*.tsv
existe. Comme ce n'est pas le cas, le fichierfile1.txt
est déplacé vers*.tsv
. C'est-à-dire: le fichier est renommé*.tsv
avec l'astérisque et tout.Exemple 3:
Si vous avez plutôt dit:
La
mv
commande est exécutée avec:Comme c'est
*.tsv
maintenant un répertoire, les fichiers finissent par y être déplacés.Maintenant: en utilisant des commandes comme
some_command *.tsv
lorsque l'intention est de conserver le caractère générique, il faut toujours le citer. En citant, vous empêchez les caractères génériques d'être étendus s'il doit y avoir des correspondances. Par exemple, ditesmkdir "*.tsv"
.Exemple 4:
L'extension peut encore être visualisée si vous faites par exemple:
Exemple 5:
Maintenant: la
mv
commande peut fonctionner et fonctionne sur plusieurs fichiers. Mais s'il y en a plus de deux, le dernier doit être un répertoire cible. (En option, vous pouvez utiliser l'-t TARGET_DIR
option, au moins pour GNU mv.)Donc ça va:
Ici
mv
serait appelé avec:et tous les fichiers se retrouvent dans le répertoire
foo
.Quant à vos liens. Vous en avez fourni un (dans un commentaire), où il
mv
n'est pas du tout mentionné, maisrename
. Si vous avez plus de liens que vous pourriez partager. Ainsi que pour les pages de manuel où vous affirmez que cela est exprimé.la source
Je sais que cela ne répond pas à votre question, mais au cas où vous cherchiez une autre façon de renommer les fichiers par rapport à votre boucle de contournement, pourquoi ne pas utiliser
find
? J'ai utilisé cette commande plusieurs fois pour remplacer les extensions de fichier dans les grands répertoires par des centaines de milliers de fichiers. Cela devrait fonctionner sur tout système compatible POSIX:Répartition des commandes:
Exemple:
la source
file.abc
->blub.xyz
dans plusieurs sous-répertoires:find . -name "file.abc" -exec sh -c 'mv "$1" "$(dirname $1)/blub.xyz"' _ {} \;
mv *.txt *.tsv
ne fonctionne pas;mv
ne peut renommer qu'un seul fichier à la fois. Vous avez soit mal compris les explications, soit elles sont fausses.mmv
etrename
peut renommer plusieurs fichiers à la fois. Mais il existe deux versions derename
around qui sont appelées différemment. Il devrait y avoir beaucoup de questions à ce sujet ici.la source
rename
, nonmv
.mv *.txt *.tsv
mv
ne voit (généralement) pas*.txt
ou*.tsv
mais les noms de fichiers développés par shell. Le nombre de fichiers dans lesquels ces caractères génériques s'étendent serait "aléatoire". La seule situation où cela fonctionne est s'il existe un fichier avec le nom*.txt
qui doit être renommé (littéralement)*.tsv
(sans citer l'bash
optionnullglob
ne doit pas être définie).foo.txt
et un nommébaz.tsv
lemv *.txt *.tsv
remplacera le.tsv
fichier existant ...Par exemple, si vous avez des fichiers
asd.txt
etqwe.txt
dans le répertoire lorsque vous exécutez la commandemv *.txt *.tsv
, il essaie de déplacer ces deux fichiers dans un répertoire nommé*.tsv
. Parce qu'il n'y a pas un tel répertoire, il donne une erreur.la source
rename(1)
rename
est un script Perl de Larry Wall, le créateur de Perl. Il prend une expression rationnelle Perl et fonctionne sur le nom de fichier.Installation
Debian / Ubuntu
Si vous devez installer
rename
sur Debian / Ubuntu, vous pouvez le fairela source
Une autre option à considérer consiste à utiliser:
*.txt
fichiers dans*.tsv
tout en préservant leurs attributs à l'aide de l'-p
indicateur.*.txt
mv
qui modifie simplement le répertoire / filename sans déplacer réellement les fichiers à moins qu'ils ne se trouvent sur une partition différente.la source