Générer automatiquement un nom de fichier à l'aide de bash


2

Supposons que j'ai de tels fichiers:

out-1.avi

Je veux avoir un morceau de code bash qui me donnera le nom de fichier suivant pour cette liste:

out-1.avi
out-2.avi
out-3.avi
etc.

modifier La chose que je dois réaliser est d’obtenir le nom de fichier suivant pour le script d’enregistrement par webcam afin qu’il ne soit pas trop écrit!

Réponses:


4

Je ne connais pas le contexte, mais la boucle suivante contient tous les éléments dont vous aurez besoin: -

n=0; while (($n < 10)); do ((++n)); echo name=out-$n.avi; done

Cela listera les 10 premiers fichiers de votre séquence.

Après votre modification, je vois plusieurs réponses.

Une modification simple de ma boucle originale serait: -

n=1; while [ -f out-$n.avi ]; do ((++n)); done; echo name=out-$n.avi

Cela fonctionnera bien pour quelques fichiers, mais deviendra de plus en plus inefficace à mesure que le nombre de fichiers atteindra des centaines.

Une solution plus efficace consisterait à enregistrer le dernier numéro de fichier dans son propre fichier: -

n=`line<avicount.text`; ((++n)); echo "$n">avicount.text; echo name=out-$n.avi

Ce script générera un nouveau nom à chaque appel, mais reposera sur avicount.text restant toujours en synchronisation avec les fichiers et les noms utilisés.

Une meilleure solution serait d'utiliser un horodatage au lieu d'un numéro de séquence: -

echo name=out-`date +%Y%M%d%H%m%S`.avi

Cela donnera un nom unique basé sur la seconde quand le script est appelé, et il peut être utile d’inclure la date de création d’un fichier dans son nom. Ce système permet également de supprimer, d’archiver ou de déplacer les fichiers à volonté, sans affecter les noms de fichiers futurs.


1
#!/bin/bash
LAST=$(find . -maxdepth 1 -name "*.avi" -type f -printf "%p\n" | sed -e s/.\\/out-//g -e s/.avi//g | sort -g | tail -1)
touch out-$(($LAST + 1)).avi
  • La première ligne sélectionne le dernier fichier avi modifié du répertoire (pas de récursif) et extrait le numéro dans son nom.
  • La deuxième ligne ajoute 1 au nom précédent et génère le fichier.

Bonne idée, mais cela ne fonctionne pas pour moi: pour une raison quelconque dans ma séquence de classement (UK) sort des endroits out-10.avi avant out-1.avi, et avec 10 fichiers le dernier sort toujours comme out-9.avi. Si vous mettez le sed commande immédiatement après la findpuis utiliser sort -gça devrait marcher.
AFH

Tu as raison. J'ai mis à jour ma réponse.
jherran

0

Vous pourriez utiliser seq pour générer les valeurs, puis touch pour créer les fichiers.

for n in $(seq 1 5)
do
    touch out-${n}.avi
done

0

En supposant que vous n’ayez pas beaucoup de fichiers dans le répertoire video (auquel cas cette approche n’est pas très efficace), cette paix de code simple peut aider:

MAX=1000;
PREFIX="out-"
SUFFIX=".avi"

for i in `seq 1 $MAX` ; do
    file="${PREFIX}${i}${SUFFIX}"

    if [ ! -e $file ] ; then
        break;
    fi
done

# this is the next available file name
echo $file

Notez que ce script remplit toutes les discontinuités dans l'ordre des fichiers. Par conséquent, si vous souhaitez définir un ordre précis ou si vous souhaitez envisager une option pour supprimer les fichiers "inutiles" de la séquence, vous pouvez utiliser une approche plus sophistiquée.


0

La solution fournie par @jherran devrait probablement répondre à vos besoins. Si vous voulez juste que le script donner Au lieu de le créer pour vous, changez "touch" en "echo" à la fin de son script.

Toutefois, cela deviendra de plus en plus lent au fur et à mesure que vous ajoutez de nombreux fichiers. Si vous avez besoin de numéros séquentiels, vous pouvez simplement écrire le numéro actuel dans un fichier, puis le relire avant d'écrire votre fichier suivant, écrivez le nouveau numéro et écrivez votre fichier. J'ai fourni un exemple de code pour le faire ci-dessous.

Toutefois, si vous n'avez pas besoin de numéros séquentiels et souhaitez simplement que les noms de fichiers ne se collent pas, les horodatages sont très utiles. Ils se classent comme vous le souhaiteriez et, si vous ne voyagez pas dans le temps, leur nombre augmente de façon monotone.

Pour répondre à la question que vous avez posée (le script shell renvoie la valeur suivante) sur la base de ma suggestion ci-dessus consistant à utiliser uniquement un fichier compteur, voici la procédure suivante:

#!/usr/bin/sh

if [ -f counter.txt ]; then
{
   VAL=`cat counter.txt`
   echo "out-$VAL.avi"
   VAL=`expr $VAL + 1`
   echo "$VAL" > counter.txt
   exit 0
}
fi
echo "out-1.avi"
echo "2" > counter.txt
exit 0

Ou, si vous voulez aller avec ma suggestion de timbres à date pour l'unicité et le tri, demandez simplement à votre programme d'écriture de fichier de récupérer le résultat de cette commande:

 date +%F-%T

ou quelle que soit la granularité des dates et des heures que vous trouvez utiles. Ce qui précède vous donnera quelque chose comme ceci:

2014-12-01-16:41:33

Slap un ". Avi" sur la fin et vous avez des noms de fichiers horodatés, à la seconde près.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.