Cette page me permet de retrouver des scripts en bash qui peuvent resservir (car on oublie lorsqu'on ne pratique pas souvent...).

Un script bash est un fichier exécutant un ensemble de commandes de façon automatisée (équivalent des macros).
Pour lancer ce fichier, on tapera dans un terminal une commande du type :

./fichier_script.sh

 

I- Problème d'espace, de tirets ou de caractères spéciaux dans les noms de fichiers et de répertoire

Voir :

II- Créer un sous-dossier identique dans tous les dossiers d'un même répertoire :

Sources :

Le script ci-dessous, crée dans le répertoire courant (là où se situe le script), un sous-dossier "FIR_école" dans tous les dossiers du répertoire courant (utile pour le drive Nextcloud par exemple).

#!/bin/bash

# $IFS permet de gérer les séparateurs comme l'espace dans les noms de dossiers
# l'option "--" dans mkdir permet d'ignorer les tirets comme séparateur
OLDIFS=$IFS
IFS=$'\n'
for d in `find . -mindepth 1 -maxdepth 1 -type d`; do
mkdir -p -- "$d"/FIR_école;
done
IFS=$OLDIFS
exit 0

 

III- Créer un sous-dossier identique dans tous les dossiers d'un même répertoire en reprenant le nom du dossier Principal :

Le script ci-dessous, crée dans le répertoire courant (là où se situe le script), un sous-dossier "RASED Nom de l'école" dans tous les dossiers du répertoire courant (utile pour le drive Nextcloud par exemple).
AVERTISSEMENT : Attention à bien placer le script dans le dossier principal et à le lancer à partir de là !

#!/bin/bash

# Ce script permet de créer, dans le répertoire courant, un sous-dossier "RASED Nom de l'école" dans tous les dossiers existants
#source : https://stackoverflow.com/questions/50285538/linux-shell-loop-for-create-file-in-each-folder

# $IFS permet de gérer les séparateurs comme l'espace dans les noms de dossiers
# l'option "--" dans mkdir permet d'ignorer les tirets comme séparateur
OLDIFS=$IFS
IFS=$'\n'
for d in `find . -mindepth 1 -maxdepth 1 -type d`; do
nomDossier=${d##*/}; #enlève "./" devant le nom du dossier
cheminDossier="$d"/RASED\ "$nomDossier"; #Nom de dossier du type "RASED Nom école" le caractère \ sert à échapper l'espace
mkdir -p -- "$cheminDossier";
done
IFS=$OLDIFS
exec bash; # évite de fermer le terminal après l'exécution du script dans un terminal (utile pour debugguer)
exit 0

 

IV- Récupérer des sous-dossiers ayant le même préfixe vers un dossier récapitulatif :

À partir du dossier racine courant, le script va copier les sous-dossiers commençant par un préfixe précis (RASED, AGRÉMENTS, ...) dans un dossier racine récapitulatif. Les commandes "echo" permettent de vérifier le contenu des variables pour le débogage.

#!/bin/bash

# Ce script permet de créer, dans le répertoire courant, un sous-dossier "Z- RASED Récap" qui recueillera tous les sous-dossiers RASED des écoles existants
#source : https://stackoverflow.com/questions/50285538/linux-shell-loop-for-create-file-in-each-folder

# $IFS permet de gérer les séparateurs comme l'espace dans les noms de dossiers
# l'option "--" dans mkdir permet d'ignorer les tirets comme séparateur
OLDIFS=$IFS
IFS=$'\n'
prefixe=RASED
echo "$prefixe"
dossierCourant=${PWD}
echo $dossierCourant
for d in `find . -mindepth 1 -maxdepth 1 -type d`; do
echo "$d"
nomDossier=${d##*/}; #sans "./" devant le nom du dossier
echo "$nomDossier"
cheminDossier="$d"/$prefixe\ "$nomDossier" #Nom de dossier du type "RASED Nom école"; avec \ pour échapper l'espace après RASED
echo "$cheminDossier"
if [ -d "$cheminDossier" ]
then
#echo "${d%/*}" #Nom du dossier parent
cheminDestination="${d%/*}"/Z-\ "$prefixe"\ Récap
echo $cheminDestination
cp -r -p -- "$cheminDossier" "$cheminDestination"; #copie récursivement en gardant les dates originales
fi
done
IFS=$OLDIFS
exec bash # évite de fermer le terminal après l'exécution du script (utile pour déboguer)
exit 0

 

Autre script beaucoup plus complet, qui permet de choisir comment récupérer les fiches : soit dans leur dossier école pour faciliter le tri, soit uniquement les fiches toutes mélangées. Seules les écoles ayant des fiches sont récupérées.

#!/bin/bash

# Ce script permet de créer, dans le répertoire courant, un sous-dossier "Z- RASED Récap" qui recueillera
# tous les sous-dossiers RASED des écoles existants OU seulement les fiches RASED (sans les sous-dossiers)
#source : https://stackoverflow.com/questions/50285538/linux-shell-loop-for-create-file-in-each-folder

# $IFS permet de gérer les séparateurs comme l'espace dans les noms de dossiers
# l'option "--" permet d'ignorer les tirets comme séparateur
OLDIFS=$IFS
IFS=$'\n'
prefixe=RASED
#echo "$prefixe"
dossierCourant=${PWD}
#echo $dossierCourant
#dossierParent="${dossierCourant%/*}" #Nom du dossier parent
dossierDestination="$dossierCourant"/Z-\ "$prefixe"\ Récap
rm -rf "$dossierDestination" #efface l'ancien dossier
mkdir "$dossierDestination"
#echo "$dossierDestination"

QuestionOuiNon () {
        QUESTION="Voulez récupérer les dossiers des écoles (si NON seules les fiches seront récueillies) ?"
        DEFAUT=true
        if [ "$DEFAUT" = true ]; then                    # Valeur par défaut définie en paramètre
                OPTIONS="[O/n]"
                DEFAUT="o"
            else
                OPTIONS="[o/N]"
                DEFAUT="n"
        fi
        read -p "$QUESTION $OPTIONS " -n 1 -s -r INPUT    # Execute au premier caractère (-n 1)
        INPUT=${INPUT:-${DEFAUT}}                        # Si $INPUT vide => remplace par $DEFAULT
        echo ${INPUT}
        if [[ "$INPUT" =~ ^[yYoO]$ ]]; then               # True si y,Y,O ou o
            REPONSE=true
        else                                              # Faux pour le reste
            REPONSE=false
        fi
}

QuestionOuiNon
#echo "$REPONSE"

for d in `find . -mindepth 1 -maxdepth 1 -type d`; do
	#echo "$d"
	nb_fichiers=0
	nomDossier=${d##*/}; #sans "./" devant le nom du dossier
	#echo "$nomDossier"	
	cheminDossier="$d"/"$prefixe"\ "$nomDossier" #Nom de dossier du type "RASED Nom école"; avec \ pour échapper l'espace après RASED
	#echo "$cheminDossier"
	nb_fichiers=$(ls -A $cheminDossier | wc -l)
	if [ "$nb_fichiers" -gt "0" ]; then # Pour ne recopier que les dossiers RASED ayant des fiches
    		#echo "dossier $cheminDossier contient $nb_fichiers fichier(s)."
    		if [ "$REPONSE" = true ]; then
			if [ -d "$cheminDossier" ]; then			
				cp -r -p -- "$cheminDossier" "$dossierDestination"; #copie récursivement en gardant les dates originales
			fi
		else
			if [ -d "$cheminDossier" ]; then
				cp -r -p -- "$cheminDossier"/* "$dossierDestination";
			fi
		fi
	fi
done
IFS=$OLDIFS
exec bash # évite de fermer le terminal après l'exécution du script (utile pour debugguer)
exit 0

 

 

V- Lister les fichiers des sous-dossiers AVEC DATE DE MODIFICATION :

Ce script doit permettre de lister tous les fichiers des sous-répertoires au même intitulé des écoles ainsi que leur date de modification. Ceci pour vérifier/contrôler leur existence par exemple.

À suivre...

 

VI- Partager avec un compte Utilisateur plusieurs dossiers commençant par le même mot clé :

Ce script doit permettre de partager tous les sous-dossiers de chaque école commençant par un mot clé avec un compte particulier. Est-ce réalisable avec webDAV ?
Piste : https://github.com/tavinus/cloudmanager ?

À faire...

VII- Déplacer des sous-dossiers commençant par le même préfixe dans un sous-dossier ARCHIVES :

Ce script permet de déplacer dans les dossiers de chaque école, tous les sous-dossiers commençant par un mot clé vers un dossier d'archivage.
Dans l'exemple ci-dessous, le script cherche dans TOUS les dossiers dans lequel il se trouve, un sous-dossier commençant par "RASED" et le déplace dans un sous-dossier "Z-Archives_2022-2023"

#!/bin/bash# Ce script permet de déplacer, dans le répertoire courant où il se trouve, dans tous les dossiers, tous les sous-dossiers ommençant par "RASED" dans un autre sous-dossier "Z-Archives_2022-2023".
#source : https://stackoverflow.com/questions/50285538/linux-shell-loop-for-create-file-in-each-folder
# $IFS permet de gérer les séparateurs comme l'espace dans les noms de dossiers
# l'option "--" dans mkdir permet d'ignorer les tirets comme séparateur
OLDIFS=$IFS
IFS=$'\n'
destination="Z-Archives_2022-2023"
for d in $(find . -mindepth 1 -maxdepth 1 -type d); do
nomDossierSource=${d##*/}; #sans "./" devant le nom du dossier
#echo "$nomDossierSource";
cheminDestination="$d"/"$destination"; #Nom du dossier de destination; utiliser \ pour échapper les espaces
#echo "$cheminDestination";
for d2 in $(find "$nomDossierSource" -mindepth 1 -maxdepth 1 -type d) ; do
nomDossierADeplacer=${d2##*/};
cheminDossierADeplacer="$d"/"$nomDossierADeplacer";
prefixe=RASED;
if [[ "$nomDossierADeplacer" == "$prefixe"* ]];then
mv "$cheminDossierADeplacer" "$cheminDestination";
fi
done
done
IFS=$OLDIFS
exec bash; # évite de fermer le terminal après l'exécution du script (utile pour debugguer)
exit 0

 

VIII- Renommer un sous-dossier qu'on trouve dans tous les dossiers :

Ce script permet de renommer un sous-dossier "ARCHIVES" qu'on trouve dans tous les dossiers où se trouve le script en "Z-Archives".

#!/bin/bash

# Ce script permet de renommer, dans le répertoire courant, dans le sous-dossier RASED,
# le sous-dossier "ARCHIVES" en "Z-archives"

# $IFS permet de gérer les séparateurs comme l'espace dans les noms de dossiers
# l'option "--" dans mkdir permet d'ignorer les tirets comme séparateur
OLDIFS=$IFS
IFS=$'\n'
ancienNom="/ARCHIVES"
nouveauNom="/Z-Archives"
for d in $(find . -mindepth 1 -maxdepth 1 -type d); do
nomDossierSource=${d##*/}; #sans "./" devant le nom du dossier
echo "$nomDossierSource";
cheminDossierARenommer="$d"/"RASED ""$nomDossierSource""$ancienNom";
echo "$cheminDossierARenommer";
cheminDossierNouveauNom="$d"/"RASED ""$nomDossierSource""$nouveauNom";
echo "$cheminDossierNouveauNom";
if [ -d "$cheminDossierARenommer" ];then
#echo "Le dossier $cheminDossierARenommer existe !";
mv "$cheminDossierARenommer" "$cheminDossierNouveauNom"
fi
done
IFS=$OLDIFS
exec bash; # évite de fermer le terminal après l'exécution du script (utile pour debugguer)
exit 0

 

IX- Pour fusionner plusieurs fichiers .csv entre-eux :

Voir cette page : https://www.baeldung.com/linux/csv-file-merging

awk '(NR == 1) || (FNR > 1)' *.csv > fichier_unique.csv

 

X- Pour ne travailler que sur des dossiers ne commençant pas par des préfixes précis :

Dans l'exemple ci-dessous, agit dans les dossiers ne commençant pas par les préfixes "0-" et "Z-" :

#!/bin/bash

# Ce script permet de créer, dans le répertoire courant, un sous-dossier "PROJET D'ÉCOLE"" dans tous les dossiers existant
#source : https://stackoverflow.com/questions/50285538/linux-shell-loop-for-create-file-in-each-folder

# $IFS permet de gérer les séparateurs comme l'espace dans les noms de dossiers
# l'option "--" dans mkdir permet d'ignorer les tirets comme séparateur
OLDIFS=$IFS
IFS=$'\n'
prefixe="PROJET_ÉCOLE"
#echo "$prefixe"
for d in `find . -mindepth 1 -maxdepth 1 -type d`; do
nomDossier=${d##*/}; #sans "./" devant le nom du dossier
debutNomDossier=${nomDossier:0:2}
if [ $debutNomDossier != "0-" ] && [ $debutNomDossier != "Z-" ] ; then
#echo $debutNomDossier
cheminDossier="$d"/"$prefixe"\ "$nomDossier"; #Nom de dossier du type "Conseils d'école Nom école"; avec \ pour échapper l'espace après RASED
mkdir -p -- "$cheminDossier";
fi
done
IFS=$OLDIFS
exec bash; # évite de fermer le terminal après l'exécution du script (utile pour debugguer)
exit 0

 

XI- Pour dézipper des fichiers zip avec mots de passe dans des sous-dossiers à partir d'une liste de mots de passe :

Ici un exemple où on place ce script dans un dossier général (celui d'une circonscription par exemple) contenant des sous-dossiers dont le nom correspond à l'UAI d'une école et dans lesquels se trouve un fichier .zip ayant le même nom que le dossier dans lequel il se trouve (n° UAI) et nécessitant un mot de passe pour le décompacter.
Les mots de passe se trouvent dans un fichier codes_ZIP.csv à la racine du dossier général où chaque ligne comprend l'UAI (nom du sous-dossier) et le mot de passe associé.
On obtient dans le dossier général, l'ensemble des fichiers dézippés (dans mon cas un .pdf et .xlsx par école).

#!/bin/bash

# Script conçu par Thierry Munoz, le 10/09/2024
# Ce script permet de balayer les sous-dossiers se trouvant dans le dossier des écoles de la circonscription où se trouve ce script
# Il dézippe ensuite tous les fichiers .zip à l'aide des codes contenus dans le fichier codes_ZIP.csv dans le dossier de la circo

# $IFS permet de gérer les séparateurs comme l'espace dans les noms de dossiers
# l'option "--" dans mkdir permet d'ignorer les tirets comme séparateur
OLDIFS=$IFS
IFS=$'\n'
for d in $(find . -mindepth 1 -maxdepth 1 -type d); do
nomDossierSource=${d##*/}; #sans "./" devant le nom du dossier
texteLigneCode="$(grep "$nomDossierSource" codes_ZIP.csv)"; #recherche un code lié à l'UAI de l'école'
codeZIP=${texteLigneCode:9}; #récupère le code pour dézipper le fichier de l'école en supprimant les 9 premiers caractères "011xxxxx;"
if [ ! -z "$codeZIP" ]; then #teste si un code de dézippage existe dans le fichier codes_ZIP.csv'
echo "code pour ZIP :" $codeZIP;
echo "$nomDossierSource";
cheminZIPEcole="$d"/$nomDossierSource.zip;
echo "$cheminZIPEcole";
unzip -P $codeZIP $cheminZIPEcole;
fi
done
IFS=$OLDIFS
exec bash; # évite de fermer le terminal après l'exécution du script (utile pour debugguer)
exit 0