Comment supprimer les anciennes sauvegardes en fonction d'une date dans le nom du file?

J'ai des sauvegardes quotidiennes nommées comme ceci:

yyyymmddhhmm.zip // pattern 201503200100.zip // backup from 20. 3. 2015 1:00 

J'essaie de créer un script qui supprime toutes les sauvegardes antérieures à 3 jours. Le script doit également être capable de supprimer tous les autres files du dossier qui ne correspondent pas au model (mais il y a un commutateur dans le script pour le désactiver).

Pour déterminer l'âge du file, je ne veux pas utiliser d'horodatages de sauvegarde car d'autres programmes manipulent également les files et peuvent être altérés.

Avec l'aide de: Supprimer les files de plus de 5 jours dans UNIX (date dans le nom du file, pas horodatage) J'ai eu:

 #!/bin/bash DELETE_OTHERS=yes BACKUPS_PATH=/mnt/\!ARCHIVE/\!backups/ THRESHOLD=$(date -d "3 days ago" +%Y%m%d%H%M) ls -1 ${BACKUPS_PATH}????????????.zip | while read A DATE B FILE do [[ $DATE -le $THRESHOLD ]] && rm -v $BACKUPS_PATH$FILE done if [ $DELETE_OTHERS == "yes" ]; then rm ${BACKUPS_PATH}*.* // but I don't know how to not-delete the files matching pattern fi 

Mais il n'arrête pas de dire:

 rm: missing operand 

Où est le problème et comment compléter le script?

Le premier problème de votre code est que vous parsingz ls . Cela signifie qu'il se cassera très facilement, si vous avez des espaces dans vos noms de files ou de directorys par exemple. Vous devriez utiliser shell globbing ou find place.

Un plus gros problème est que vous ne lisez pas correctement datatables. Votre code:

 ls -1 | while read A DATE B FILE 

ne remplira jamais $FILE . La sortie de ls -1 est juste une list de noms de files, donc, à less que ces noms de file contiennent des espaces, seule la première des 4 variables que vous donnez à read sera renseignée.

Voici une version de travail de votre script:

 #!/usr/bin/env bash DELETE_OTHERS=yes BACKUPS_PATH=/mnt/\!ARCHIVE/\!backups THRESHOLD=$(date -d "3 days ago" +%Y%m%d%H%M) ## Find all files in $BACKUPS_PATH. The -type f means only files ## and the -maxdepth 1 ensures that any files in subdirectories are ## not included. Combined with -print0 (separate file names with \0), ## IFS= (don't break on whitespace), "-d ''" (records end on '\0') , it can ## deal with all file names. find ${BACKUPS_PATH} -maxdepth 1 -type f -print0 | while IFS= read -d '' -r file do ## Does this file name match the pattern (13 digits, then .zip)? if [[ "$(basename "$file")" =~ ^[0-9]{12}.zip$ ]] then ## Delete the file if it's older than the $THR [ "$(basename "$file" .zip)" -le "$THRESHOLD" ] && rm -v -- "$file" else ## If the file does not match the pattern, delete if ## DELETE_OTHERS is set to "yes" [ $DELETE_OTHERS == "yes" ] && rm -v -- "$file" fi done 

n'oublie pas la ligne sed entre ls -1 et while read , cette ligne est importante.

pour la première question, je suggère: (un rlocation awk je n'ai pas pu find un équivalent sed)

 ls -1 ${BACKUPS_PATH}????????????.zip |\ awk -F. '{printf "%s %s\n",$1,$0 ;}' |\ while read DATE FILE do [[ $DATE -le $THRESHOLD ]] && rm -v $BACKUPS_PATH$FILE done 

à condition que l'arithmétique du shell soit au less de 37 bits pour effectuer le test $DATE -le $THRESHOLD .