J'ai un tas de files dans le format suivant:
2014-11-19.8.ext 2014-11-26.1.ext 2014-11-26.2.blah.ext 2014-11-26_3.ext 2014-11-26.4.stuff_here.ext 2014-12-03.1. could be anything.ext 2014-12-032b.ext 2014-11-26 613 adva.ext
Mon but est de parcourir la list complète des files et de prendre le format de date de YYYY-MM-DD
et de le stocker dans une variable au format YYYYMMDD
pour traitement ultérieur (dans mon cas, il sera poussé dans une command touch
).
Donc normalement je ferais correspondre cette expression régulière: (\d{4})-(\d{2})-(\d{2}).*
Et puis utiliser $1$2$3
pour get mon model désiré, mais je ne suis pas sûr de savoir comment faire dans bash
/ zsh
.
Comment cela peut-il être fait dans un script shell en tant que tel?
Utilisation de l' expansion des parameters
$ touch 2014-11-19.8.ext 2014-11-26.1.ext $ for f in *.ext; do d="${f:0:4}${f:5:2}${f:8:2}"; echo "$d"; done 20141119 20141126
${f:0:4}
signifie 4 caractères commençant par l'index 0
et f
nom de la variable echo "$d"
par votre code Pour mettre en boucle chaque file du directory courant et comparer leurs noms de files au model désiré, définissez une variable contenant les pièces de la date
for f in * do [[ $f =~ ^([0-9][0-9][0-9][0-9])-([0-9][0-9])-([0-9][0-9])(.*) ]] && yourvar="${BASH_REMATCH[1]}${BASH_REMATCH[2]}${BASH_REMATCH[3]}" done
Cela utilise bash [[
possibilité d'utiliser la correspondance d'expressions régulières pour placer les pièces de date dans le tableau BASH_REMATCH.
Vous pouvez le faire de façon interactive en utilisant GNU sed
:
$ sed 's/^\([0-9]\{4\}\)-\([0-9]\{2\}\)-\([0-9]\{2\}.*\)/\1\2\3/g' stuff.txt
Pour plusieurs files (si dans le même directory et aucun autre file considéré dans le directory):
for file in * do if [ -f "$file" ] then sed 's/^\([0-9]\{4\}\)-\([0-9]\{2\}\)-\([0-9]\{2\}\).*/\1\2\3/g' "$file" fi done
Voici une façon zsh
de faire cela, sans loops:
autoload -U zmv zmv -n '([0-9](#c4))-([0-9](#c2))-([0-9](#c2))(*)' '$1$2$3$4'
[0-9](#c4)
signifie tout chiffre répété 4 fois $1
– $2
réfèrent à la parenthèse précédemment utilisée -n
empêche l'exécution (printing uniquement), supprime ce drapeau si vous êtes satisfait du résultat Comme zsh
prend soin de globuler tous les cas de coin (espaces blancs, caractères spéciaux, etc.) doivent être pris en count automatiquement.
Si vous utilisez GNU Coreutils, vous avez ceci:
$ date --date=2014-11-13 +"%Y%m%d" 20141113
Toutefois:
$ date --date=2014-11-130ABCJUNK +"%Y%m%d" date: invalid date '2014-11-130ABCJUNK'
Ainsi, la tâche est beaucoup plus simple: extraire les dix premiers caractères de chaque nom de file YYYY-MM-DDetc
pour get la date seule, puis passer à la date
de reformatting.
Mais si nous sums sur GNU Coreutils, nous pouvons ignorer la command date
car touch
a exactement la même option --date=STRING
.
for file in * ; do date=${file%${file##??????????}} # chop all but first ten touch --date=$date -- "$file" done
Mais pourquoi ce découpage de dix caractères dans le mode POSIX est-il portable alors que nous nous appuyons sur le touch
de GNU Coreutils?
for file in * ; do date=${file:0:10} touch --date=$date -- "$file" done
Essayez la substitution de motif:
${parameter/pattern/ssortingng}
paramètre est le nom de base du file. motif est un tiret. Dans ce / – replace le model globalement. string est vide, puisque vous voulez supprimer les tirets.
mv "${f}" "${f//-/}"
Caveat: Je n'ai pas eu ce travail avec le cas des espaces dans l'extension.