Script ou programme Linux pour raccourcir les noms de fichiers

8

Je n'ai pas eu beaucoup de succès pour trouver une version Linux de namemangler , dont j'ai besoin pour renommer 1000 fichiers afin qu'ils soient lisibles sous Windows.

Quelqu'un connaît-il un programme Linux capable de faire cela?

Si ce n'est pas le cas, un script peut fonctionner car je n'ai besoin que de renommer tous les fichiers d'un dossier en, disons, les 16 premiers caractères. Je soupçonne que la route du script pourrait être utile, mais je ne sais pas par où commencer.

Grimlockz
la source
2
Vous pourriez probablement écrire rapidement un script Python ou Perl ou Ocaml ou Ruby.
Pourquoi ne pouvez-vous pas simplement utiliser un système de fichiers vfat, qui autorise les noms de fichiers longs?
wnoise
2
Par curiosité, quelle est la durée des noms et que contiennent-ils pour qu'ils ne soient pas reconnus par Windows?
Bobby

Réponses:

10

Sur Debian, Ubuntu et dérivés, si vous entrez man renameà l'invite de commande, vous obtiendrez la page de manuel pour un utilitaire de changement de nom qui permet d'utiliser des commandes d'expression régulière de type Perl arbitraires dans le changement de nom.

Par exemple, cela raccourcira (en tronquant) tous les fichiers du répertoire actuel à une longueur de cinq:

rename 's/^(.{5}).*/$1/' *

Il fonctionne en capturant les cinq premiers caractères puis en les utilisant dans la substitution, en supprimant le reste.

Un autre exemple est de raccourcir les noms de fichiers (sans extension) à cinq caractères tout en préservant l'extension:

rename 's/^(.{5}).*(\..*)$/$1$2/' *

Il capture deux groupes, le premier étant les cinq premiers caractères, le second étant l'extension. Cela tournerait myCarefullyCraftedDocument.pdfen myCar.pdf.

Avertissement: utilisez-le soigneusement, de préférence sur une copie de votre répertoire, ou en effectuant d'abord des sauvegardes. Tu étais prévenu!! Au minimum, utilisez d' rename -nabord, qui vous montrera ce qui serait fait sans le faire.


la source
1
cela va-t-il se débarrasser du préfixe comme en PDF? et qu'arriverait-il aux fichiers du même nom une fois raccourcis?
Cet exemple particulier le sera, oui. Vous pouvez écrire une expression régulière pour laisser l'extension seule. Je mettrai à jour la réponse. Il protège également contre l'écrasement des fichiers qui existent déjà, donc les renommages ultérieurs échoueront.
merci pour votre aide à ce sujet - je suis très reconnaissant. J'ai un petit problème si certains des fichiers PDF seront renommés en 5 permet de dire ce qui arriverait aux PDF qu'il essaie de renommer avec le même nom? Est-ce un moyen de simplement ajouter un numéro unique à tous ceux avec celui-ci? voir ci-dessous ename -n 's / ^ (. {5}). * (\ .. *) $ / $ 1 $ 2 /' * Annexes 123114345234525.pdf renommé Annex.pdf Annexes 123114432452352.pdf renommé Annex.pdf
@Grimlockz, je ne pense pas que vous puissiez mettre ce genre d'intelligence dans le regex lui-même. Ce que vous devrez peut-être faire est d'écrire un script pour envelopper le renommage avec ce genre d'intelligence, et il vaut mieux le poser comme une question distincte afin que plus de gens répondent que moi.
@Grimlockz C'est pourquoi vous ne voulez pas tout faire dans une expression régulière. Vous serez plus heureux et mieux d'écrire un script qui utilise des expressions régulières.
Spencer Rathbun
3

Vous pouvez déplacer des fichiers en conflit vers un autre répertoire:

for i in *
do
    j=${i:0:16}

    if [ -e "$j" ]
    then
        mv "$i" /path/to/rename/later
    else
        mv "$i" "$j"
    fi
done
kev
la source
1

Vous pouvez écrire un script pour raccourcir les noms de fichiers et supprimer les caractères que Windows n'aime pas en quelques lignes de bash. Attention, code non testé, saisi directement dans mon navigateur.

shopt -s dotglob extglob
for x in *; do
  y=${x//+([!-!#$%&'().0-9@A-Z^_`a-z{}~])/_}  # change all problematic characters to _
  if [[ $y = .* ]]; then y=_${y#.}; fi        # change dot files to begin with _
  y=${y:0:16}                                 # truncate names
  y=${y,,}                                    # convert to lowercase
  if [[ -e $y || $y =~ ^(aux|clock\$|com[0-9]|con|lpt[0-9]|nul|prn)(\.*)?$ ]]; then
    # The file exists or is a DOS/Windows reserved name.
    # Change foo.bar to foo~1.bar, foo~2.bar, ... (I ignore the length restriction here)
    i=1
    if [[ $y =~ \. ]]; then
      prefix=${y%%.*}; suffix=.${y#*.}
    else
      prefix=$y; suffix=
    fi
    y=${prefix}~$i$suffix
    while [[ -e $y ]]; do
      ((++i))
      y=${prefix}~$i$suffix
    done
  fi
  mv -- "$x" "$y"
done

Si vous avez besoin de récursivement dans des sous-répertoires, appelez un script shell à partir de find -depth -exec …. Ou utilisez zsh au lieu de bash; dans zsh, **/*(od)s'étend à tous les fichiers du répertoire courant, récursivement, avec des fichiers imbriqués plus profondément en premier.

Gilles 'SO- arrête d'être méchant'
la source
1

Les scripts shell / python / perl pour ce genre de chose sont très bien, mais il semble qu'une application gui serait la meilleure pour vous, donc je recommanderais pyRenamer , qui peut faire exactement ce que vous voulez, entre autres choses (opérations courantes simples via des préréglages [se débarrasser des espaces, tronquer le nom de fichier d'un point à un autre], recherche / remplacement simple, regex compliqué, prévisualisateur, etc.).

Votre distribution pourrait même l'avoir dans son référentiel de logiciels (Fedora le fait).

rsaw
la source
0

Certains systèmes n'ont pas la renamecommande, donc comme alternative à la réponse de paxdiablo, voici comment faire la même chose avec mv.

for f in *.pdf; do 
    tmp=`echo $f | sed -r 's//^(.{5}).*(\..*)$/$1$2/'`
    mv -b ./"$f" ./"$tmp"
done

Le -bdrapeau en mouvement crée une sauvegarde des fichiers qui seraient supprimés ou écrasés. En modifiant le modèle de glob dans la boucle for, vous pouvez ajuster les fichiers sur lesquels il s'exécute, en utilisant *lui-même pour s'exécuter sur tous les fichiers.

Spencer Rathbun
la source
1
Pas besoin d'utiliser echoune pipe (cela pourrait être très cher si vous avez beaucoup de fichiers), utilisez plutôt un hérédoc ou une herestring.
Chris Down
1
@ChrisDown voir ici . Selon l'article du wiki , les processus canalisés sont bifurqués, mais cela ne dit rien sur leur exécution dans leurs propres shells.
Spencer Rathbun
1
Par exemple, notez la différence entre eval 'echo $BASH_SUBSHELL'et eval 'echo $BASH_SUBSHELL' | cat.
Chris Down
2
Je viens de faire un test rapide, timeen utilisant une boucle echo $i | sedet une autre sed ... <<<$i, et l'héritage a pris environ 2/3 du temps de l'écho.
Kevin
1
@SpencerRathbun Oui. <<démarre un <i> doc </i> ici, qui est multiligne et nécessite des délimiteurs. <<<crée une <i> chaîne </i> ici, qui ne prend qu'une variable / chaîne. Essayez, var=abc // cat<<<$var // cat <<$var.
Kevin
0

Si vous avez besoin d'expérimenter avec renommer des fichiers et que vous avez installé des bibliothèques KDE sur votre système (ou si cela ne vous dérange pas de les ajouter), consultez krename.

Il vous permet de faire plusieurs tâches de changement de nom simples directement avec ses outils et permet également des expressions régulières pour des situations plus compliquées.

Il vous montre un aperçu des fichiers renommés lorsque vous créez les conditions de changement de nom. Il vous permet également de renommer à nouveau les mêmes fichiers, ce qui est utile si vous voulez faire quelque chose de compliqué alors que le faire par étapes réduirait la complexité de chaque étape en quelque chose que vous pouvez comprendre rapidement.

Joe
la source
-1
for file in *; do
    mv "$file" $(echo "$file" | sed -e 's/[^A-Za-z0-9._-]/_/g')
done &
Jairo Bernal
la source