#1 Le 08/08/2017, à 20:09
- kholo
[TUTO Bash] rangement automatique fichiers par extension
Bonjour à tous,
Voici un script pour organiser des fichiers selon l'extension ou leur type mime
edit du 2020 05 22 : je me rend compte que j'avais laissé pas mal de coquilles alors je vais donner sa chance à mon script en les corrigeant et en le mettant un peu au goût du jour et de mes connaissances !
C'est l'utilisateur qui va choisir le nom du dossier avec lequel chaque extension sera associée.
voici une vidéo de l'utilisation : une vidéo de démonstration
Dorian (je l'ai appelé ainsi) va nous aider à ranger des fichiers contenus dans un dossier
son principe de fonctionnement repose sur les extensions des fichiers.
En fonction de l'extension, Dorian se baser sur une base personnelle et créera un dossier pour y déplacer le fichier
l'association entre extension et nom de dossir pourra choisir lors de la première découverte de l'extension et modifiée par la suite.
Si le fichier ne comporte pas d'extension Dorian se contente de le ranger par Type Mime et
créera donc des dossiers et sous dossiers en fonction des types Mime trouvés
PARTIE 1
le script principal dorian
créez un dossier
mkdir -p $HOME/bin
créez un fichier
touch $HOME/bin/dorian
le rendre exécutable
chmod +x $HOME/bin/dorian
éditer avec
gedit $HOME/bin/dorian
et copier le texte suivant
#!/bin/bash
# nautilus "${PWD}" ; exit 0
#**************************************************************************
NOM_LOGICIEL="${0##*/}"
FONCTION="Dorian...
va nous aider à ranger des fichiers contenus dans un dossier
son principe de fonctionnement repose sur les extensions de fichier.
En fonction de l'extension, Dorian va alimenter une base personnelle et créera un dossier
que chacun pourra choisir lors de la première découverte de l'extension.
Si le fichier ne comporte pas d'extension Dorian se contente de le ranger par Type Mime et
créera donc des dossiers et sous dossiers en fonction des types Mime trouvés
"
VERSION="0.007"
#NOTES DE VERSIONS
#----------------------------------------------
#
# 0.007
# [ VS [[ à voir !
# 0.006
# nettoyage
# 0.005
# suppression des "function"
# 0.004
# premiers tests et mises au point des fonctions
#----------------------------------------------
#echo "lancement ${NOM_LOGICIEL}..."
# zenity --info --text "${@}"
# exit 0
#**************************************************************************
#INITIALISATION DES VARIABLES
#durée d'exécution pour horodatage du log
START=$(date +%s.%N)
#DIR_CONF
DIR_CONF="${HOME}/.config/kholo/${NOM_LOGICIEL}"
# Création du dossier si il n'existe pas
[ -d "${DIR_CONF}" ] || mkdir -p "${DIR_CONF}"
FICHIER_LOG="${DIR_CONF}/${NOM_LOGICIEL}.log"
FILE_EXT_CONNUES="${DIR_CONF}/extConnues.txt"
# Création du fichier si il n'existe pas
[ -f "${FILE_EXT_CONNUES}" ] || > "${FILE_EXT_CONNUES}"
#DIR_ORIG
DIR_ORIG=""
#DIR_DEST
DIR_DEST=""
LES_EXT_CONNUES=()
LES_NOMS_DOSSIERS=()
#**************************************************************************
#ETAGE JOURNAL
_journal () {
#journal cumulé
[ -f "${FICHIER_LOG}" ] || > "${FICHIER_LOG}"
#on vide le log ou on le crée si il n'existe pas
# > "${FICHIER_LOG}"
journal "ouverture - $(date)"
journal "Ligne ${LINENO}--\t\t------------------------"
}
journal () {
local NOW=$(date +%s.%N)
local DIFF=$(echo "${NOW} - ${START}" | bc)
echo -e "[${DIFF}] ${@}" >> "${FICHIER_LOG}"
}
_journal
journal "Ligne ${LINENO}--\t\t\tchargement"
#**************************************************************************
#CHARGEMENT DES BASES
nettoyerFichier () {
journal "Ligne ${LINENO}--\t\t-> ${FUNCNAME[0]}"
# journal "Ligne ${LINENO}--\t\tArguments -> ${@}"
#range les lignes d'un fichier dans l'ordre alphabétique
sort -d -f -b -u "${@}" | tee "${@}.new" && mv "${@}.new" "${@}"
#supprime les lignes vides d'un fichier
sed -i '/^$/d' "${@}"
}
chargerEXT_CONNUES () {
journal "Ligne ${LINENO}--\t\t-> ${FUNCNAME[0]}"
# journal "Ligne ${LINENO}--\t\tArguments -> ${@}"
#Initialisation des bases
LES_EXT_CONNUES=()
LES_NOMS_DOSSIERS=()
#Chargement des bases
local LIGNE
for LIGNE in $(cat "${FILE_EXT_CONNUES}")
do
LES_EXT_CONNUES+=( ${LIGNE%%;*} )
LES_NOMS_DOSSIERS+=( ${LIGNE##*;} )
done
}
nettoyerFichier "$FILE_EXT_CONNUES" >/dev/null
chargerEXT_CONNUES
journal "Ligne ${LINENO}--\t\tchargement"
#**************************************************************************
#Rangement par type Mine en cas de manque d'extension
getTYPE_MIME_FICHIER () {
journal "Ligne ${LINENO}--\t\t-> ${FUNCNAME[0]}"
# journal "Ligne ${LINENO}--\t\tArguments -> ${@}"
local CHEMIN_FICHIER="$1"
local LE_TYPE_MIME="$(file -b -i "${CHEMIN_FICHIER}")"
if [ $? -eq 1 ]
then
journal "Ligne ${LINENO}--\t\t------------\nPROBLEME : \n${PWD} \n${CHEMIN_FICHIER} \n${LE_TYPE_MIME}\n-------------"
else
journal "Ligne ${LINENO}--\t\t${CHEMIN_FICHIER} \n->${LE_TYPE_MIME}"
TYPE_MIME_partie1="${LE_TYPE_MIME%%; *}"
echo "${TYPE_MIME_partie1}"
fi
journal "Ligne ${LINENO}--\t\tfin du découpage TYPE_MIME"
}
rangerFichierParTypeMime () {
journal "Ligne ${LINENO}--\t\t-> ${FUNCNAME[0]}"
# journal "Ligne ${LINENO}--\t\tArguments -> ${@}"
local CHEMIN_FICHIER="${@}"
local LE_DOSSIER="0_$(getTYPE_MIME_FICHIER "${@}" 1)"
journal "Ligne ${LINENO}--\t\tdéplacement de \n${CHEMIN_FICHIER} \nvers \n${DIR_DEST}/${LE_DOSSIER}"
deplacerFichier "${CHEMIN_FICHIER}" "${DIR_DEST}/${LE_DOSSIER}"
}
journal "Ligne ${LINENO}--\t\tchargement"
#**************************************************************************
deplacerFichier () {
journal "Ligne ${LINENO}--\t\t-> ${FUNCNAME[0]}"
# journal "Ligne ${LINENO}--\t\tArguments -> ${@}"
local unFichier
local uneDestination
unFichier="${1}"
uneDestination="${2}"
journal "Ligne ${LINENO}--\t\tunFichier : ${unFichier}"
journal "Ligne ${LINENO}--\t\tuneDestination : ${uneDestination}/"
[ -d "${uneDestination}" ] || mkdir -p "${uneDestination}" && \
journal "Ligne ${LINENO}--\t\tcréation dossier ${uneDestination} réussie"
mv "${unFichier}" "${uneDestination}/" && \
journal "Ligne ${LINENO}--\t\tdéplacement réussi" || \
journal "Ligne ${LINENO}--\t\tdéplacement échec"
}
journal "Ligne ${LINENO}--\t\tchargement"
#**************************************************************************
#ETAGE TRAITEMENT SELON EXTENSION
frm_EntryChoixType () {
journal "Ligne ${LINENO}--\t\t-> ${FUNCNAME[0]}"
# journal "Ligne ${LINENO}--\t\tArguments -> ${@}"
zenity --entry \
--title="Choisir un type" \
--text="l'extension ${@} n'a pas été trouvée ; \najouter aux motifs de type :" \
--entry-text=$(echo "${LES_NOMS_DOSSIERS[@]}" | tr ' ' '\n' | sort -u)
}
ajouterMotifExtension () {
journal "Ligne ${LINENO}--\t\t-> ${FUNCNAME[0]}"
# journal "Ligne ${LINENO}--\t\tArguments -> ${@}"
Nouveau_Dossier="$(frm_EntryChoixType "${1}")"
# if [ ${#Nouveau_Dossier} -gt 0 ]
# then
journal "Ligne ${LINENO}--\t\t# Ajouter aux extensions connues ${@};${Nouveau_Dossier}"
if [ ${#@} -ne 0 ] && [ ${#Nouveau_Dossier} -ne 0 ]
then
echo "${@};${Nouveau_Dossier}" | tee -a "${FILE_EXT_CONNUES}"
LES_EXT_CONNUES+=( ${@} )
LES_NOMS_DOSSIERS+=( ${Nouveau_Dossier} )
else
return 1
fi
# else
journal "Ligne ${LINENO}--\t\tnewMotifExt = ${Nouveau_Dossier}" # TODO ?
# return 1
# fi
}
chercherExtdansDB () {
journal "Ligne ${LINENO}--\t\t-> ${FUNCNAME[0]}"
# journal "Ligne ${LINENO}--\t\tArguments -> ${@}"
# recherche dans les extensions connues
# renvoie un dossier si trouvé sinon rien
local leTest="${@}" # c'est l'extension à tester
journal "Ligne ${LINENO}--\t\t#LES_EXT_CONNUES : ${#LES_EXT_CONNUES[@]}"
for (( c=0;c<${#LES_EXT_CONNUES[@]};c++ ))
do
# journal "Ligne ${LINENO}--\t\t${leTest} == ${LES_EXT_CONNUES[$c]} ?"
if [[ "${leTest}" == "${LES_EXT_CONNUES[$c]}" ]]
then
journal "Ligne ${LINENO}--\t\tOUI extension trouvée : ${LES_NOMS_DOSSIERS[$c]}"
echo "${LES_NOMS_DOSSIERS[$c]}"
break
# else
# journal "Ligne ${LINENO}--\t\tNON"
fi
done
}
rangerFichiersParExtension () {
journal "Ligne ${LINENO}--\t\t-> ${FUNCNAME[0]}"
# journal "Ligne ${LINENO}--\t\tArguments -> ${@}"
CHEMIN_FICHIER="${@}" ;
NOM_FICHIER="${CHEMIN_FICHIER##*/}"
EXT_FICHIER="${NOM_FICHIER##*.}"
local leCHEMIN="$(chercherExtdansDB "${EXT_FICHIER}")"
journal "Ligne ${LINENO}--\t\tleCHEMIN : ${leCHEMIN}"
if [ "${#leCHEMIN}" -eq 0 ]
then
journal "Ligne ${LINENO}--\t\textension inconnue"
local NOUVEAU_DOSSIER="$(ajouterMotifExtension "${EXT_FICHIER}")"
if [ ! ${#NOUVEAU_DOSSIER} -eq 0 ]
then
NOUVEAU_DOSSIER="${NOUVEAU_DOSSIER##*;}"
deplacerFichier "${CHEMIN_FICHIER}" "${DIR_DEST}/${NOUVEAU_DOSSIER}"
nettoyerFichier "$FILE_EXT_CONNUES" >/dev/null
chargerEXT_CONNUES
else
journal "Ligne ${LINENO}--\t\tl'extension ne sera pas ajoutée"
fi
else
journal "Ligne ${LINENO}--\t\tDéplacement du fichier selon extension"
deplacerFichier "${CHEMIN_FICHIER}" "${DIR_DEST}/${leCHEMIN[$c]}"
fi
}
traiterFichier () {
journal "Ligne ${LINENO}--\t\t----------------------------------"
journal "Ligne ${LINENO}--\t\t-> ${FUNCNAME[0]}"
# journal "Ligne ${LINENO}--\t\tArguments -> ${@}"
CHEMIN_FICHIER="$(readlink -f "${@}")"
NOM_FICHIER="${CHEMIN_FICHIER##*/}"
EXT_FICHIER="${NOM_FICHIER##*.}"
if [ "${EXT_FICHIER}" == "${NOM_FICHIER}" ]
then
journal "Ligne ${LINENO}--\t\t-------------pas d'extension !-------------"
rangerFichierParTypeMime "${CHEMIN_FICHIER}"
else
journal "Ligne ${LINENO}--\t\tl'extension est ${EXT_FICHIER}"
rangerFichiersParExtension "${CHEMIN_FICHIER}"
fi
}
journal "Ligne ${LINENO}--\t\tchargement"
#**************************************************************************
#Etage traitement des arguments du script
setDIR_DEST () {
journal "Ligne ${LINENO}--\t\t-> ${FUNCNAME[0]}"
# journal "Ligne ${LINENO}--\t\tArguments -> ${@}"
DIR_DEST="${DIR_ORIG}"
}
estLienDossierFichier () {
journal "Ligne ${LINENO}--\t\t-> ${FUNCNAME[0]}"
# journal "Ligne ${LINENO}--\t\tArguments -> ${@}"
if [ -L "${@}" ]
then
journal "error : $@ est un lien"
else
if [ -d "${@}" ]
then
journal "error : $@ est un dossier"
else
if [ -f "${@}" ]
then
# DIR_ORIG="${@}"
DIR_ORIG="${@%/*}"
setDIR_DEST
traiterFichier "${@}"
fi
fi
fi
}
traiterLesArguments () {
journal "Ligne ${LINENO}--\t\t-> ${FUNCNAME[0]}"
# journal "Ligne ${LINENO}--\t\tArguments -> ${@}"
IFS=$'\n'
local url
for url in $@
do
journal "---------------------------------------------"
journal "Ligne ${LINENO}--\t\turl : ${url}"
estLienDossierFichier "${url}"
done
}
selectionnerTousLesFichiers () {
journal "Ligne ${LINENO}--\t\t-> ${FUNCNAME[0]}"
for FILE in *
do
if [ -e "$(readlink -f "${FILE}")" ]
then
estLienDossierFichier "$(readlink -f "${FILE}")"
else
journal "erreur avec ${FILE}"
fi
done
}
afficher_ExtConnues () {
journal "Ligne ${LINENO}--\t\t-> ${FUNCNAME[0]}"
cat "${FILE_EXT_CONNUES}"
echo -e "le fichier est : ${FILE_EXT_CONNUES}"
exit 66
}
afficher_fichier_log () {
cat "${FICHIER_LOG}"
echo -e "le fichier est : ${FICHIER_LOG}"
exit 67
}
vider_fichier_log () {
>"${FICHIER_LOG}"
echo -e "le fichier est vidé : \n${FICHIER_LOG}"
exit 67
}
afficher_aide () {
cat <<EOF
dorian va nous aider à ranger nos fichiers
lancez dorian [Ff:hHvVcl]
dorian -h ou -H
cette aide
dorian -v ou -V
la version de ce script
dorian -F
range tous les fichiers trouvés dans le répertoire courant
dorian -f 'un Fichier'
range 'un Fichier' mettre -f pour chaque fichier
dorian "/un/fichier/ici" "/un/fichier/la"
liste de fichiers séparés par des sauts de ligne ou des espaces
dorian -c
affiche le fichier des extentions de l'utilisateur courant et son emplacement.
dorian -l
affiche le fichier log de l'utilisateur courant et son emplacement.
EOF
afficher_version
}
afficher_version () {
echo "$0 version : $VERSION"
}
traiterLesOptions () {
journal "Ligne ${LINENO}--\t\t-> ${FUNCNAME[0]}"
while getopts cFf:hHlvV option # : pour dire que l'option attend un argument
do
case "${option}" in
c ) afficher_ExtConnues ;;
F ) selectionnerTousLesFichiers ;;
f ) [ -e "$(readlink -f "${OPTARG}")" ] && estLienDossierFichier "$(readlink -f "${OPTARG}")" ;;
h | H ) afficher_aide ;;
l ) afficher_fichier_log ;;
L ) vider_fichier_log ;;
v | V ) afficher_version ;;
esac
done
shift $(($OPTIND-1))
[ -n $1 ] && journal "Ligne ${LINENO}--\t\tje n'ai pas traité cela : ${@}"
}
voirArguments () {
journal "Ligne ${LINENO}--\t\t-> ${FUNCNAME[0]}"
if [ ! ${#@} -eq 0 ]
then
journal "Ligne ${LINENO}--\t\tNbre d'arguments trouvés : ${#@}"
case $@ in
-* ) traiterLesOptions "$@" ;;
*) traiterLesArguments "$@" ;;
esac
else
journal "Ligne ${LINENO}--\t\tpas d'arguments trouvés"
afficher_aide
echo "erreur 65 ; arguments manquants"
exit 65
fi
}
journal "Ligne ${LINENO}--\t\tchargement"
#**************************************************************************
# nautilus "${PWD}"
# nautilus "$HOME/.config/kholo/dorian"
# exit 0
IFS=$'\n'
voirArguments $@
journal "---------------------------------------------
Ligne ${LINENO}--\t\tfermeture"
#**************************************************************************
exit 0
PARTIE 2
un lanceur pour nautilus (à adapter si vous avez choisi un autre dossier que $HOME/bin)
touch $HOME/.local/share/nautilus/scripts/dorian
le rendre exécutable
chmod +x $HOME/.local/share/nautilus/scripts/dorian
puis on l'édite
gedit $HOME/.local/share/nautilus/scripts/dorian
et copiez le code suivant
sa seule fonction est d'envoyer la liste des fichiers sélectionnés au script qui pourra donc être facilement adapté pour la LdC ou un autre gestionnaire de fichiers
#!/bin/bash
IFS=$'\n'
leCHEMIN="$HOME/bin/dorian"
"${leCHEMIN}" $NAUTILUS_SCRIPT_SELECTED_FILE_PATHS
PARTIE 3
maintenant un fichier pour éditer les associations entre extensions et noms de dossier
on va créer un dossier spécifique
mkdir -p "$HOME/.config/kholo/dorian"
et un fichier de configuration à y mettre
exemple de fichier de configuration (facilement adaptable) :
extension puis point virgule puis nom de dossier
exemple : bin;programmes => les bin iront dans le dossier programmes
plusieurs extensions peuvent aller dans le même dossier mais si une même extension est plusieurs fois, seule la première sera prise en considération
(il faut que je vérifie... et surtout que je mette une routine pour faire du nettoyage si cela arrive... encore que ce ne puisse arriver que si une édition est faite à la main !)
NB ce fichier est mis à jour automatiquement chaque fois que vous ajoutez des extensions durant un rangement
gedit "$HOME/.config/kholo/dorian/extConnues.txt"
bin;programmes
bz2;compression
conf;scripts
db;bases
deb;scripts
doc;bureautique
exe;programmes
gif;images
gz;compression
html;texte
jp2;images
jpeg;photos
mid;musique
ods;bureautique
odt;bureautique
pdf;bureautique
php;scripts
png;images
py;scripts
sh;scripts
sql;bases
tgz;compression
txt;texte
xlsx;bureautique
xz;compression
zip;compression
PARTIE 4 : Utilisation
maintenant allez dans un dossier et sélectionnez des fichiers
puis clic droit / scripts / dorian
et, donnez un nom pour le dossier chaque fois qu'une extension inconnue est trouvée
chaque fichier dont l'extension est identique sera rangé avec ses congénères
les fichiers sans extensions seront rangés par type mime dans un dossier commençant par 0type/nomdutype
Dernière modification par kholo (Le 22/05/2020, à 12:34)
Hors ligne
#2 Le 19/08/2017, à 09:53
- kholo
Re : [TUTO Bash] rangement automatique fichiers par extension
édit du 22 mai 2020...
comme j'ai mis la version 007 dans le premier post, je modifie rapidement le script ici... et je reviendrai mettre une version plus sympa...
je nettoie rapidement le code avant de le faire évoluer autant dans son comportement que dans certaines lourdeurs
=> le journal est tenu dans le dossier /tmp (que je met en RAM ce qui est mieux pour les ssd)
édit du 25 mai 2020...
je vire ma version du 22 et met une version 009 corrigée avec les préconisations de Watael... j'ai suivi la quasi totalité des conseils...
je répond dans un post au point par point dans la suite de ce fil...
#!/bin/bash
# nautilus "${PWD}" ; exit 0
#**************************************************************************
nom_logiciel="${0##*/}"
fonction_logiciel="Dorian...
va nous aider à ranger des fichiers contenus dans un dossier
son principe de fonctionnement repose sur les extensions de fichier.
En fonction de l'extension, Dorian va alimenter une base personnelle et créera un dossier
que chacun pourra choisir lors de la première découverte de l'extension.
Si le fichier ne comporte pas d'extension Dorian se contente de le ranger par Type Mime et
créera donc des dossiers et sous dossiers en fonction des types Mime trouvés
"
version_logiciel="0.009"
#NOTES DE VERSIONS
#----------------------------------------------
# 0.009 corrections suite aux observations, conseils et préconisations de Watael
# https://forum.ubuntu-fr.org/viewtopic.php?pid=22289390#p22289390
# 0.008
# nettoyage rapide 2020
# 0.007
# [ VS [[ à voir !
# 0.006
# nettoyage
# 0.005
# suppression des "function"
# 0.004
# premiers tests et mises au point des fonctions
#----------------------------------------------
#echo "lancement ${nom_logiciel}..."
# zenity --info --text "${@}"
# exit 0
#**************************************************************************
#INITIALISATION DES VARIABLES
#durée d'exécution pour horodatage du log
debut=$(date +%s.%N)
#dossier_conf
dossier_conf="${HOME}/.config/kholo/${nom_logiciel}"
## Création du dossier si il n'existe pas
[ -d "${dossier_conf}" ] || mkdir -p "${dossier_conf}"
## je met tmp en ram donc je vais m'en servir pour log plus vite
# fichier_log="${dossier_conf}/${nom_logiciel}.log"
fichier_log="/tmp/${nom_logiciel}.log"
## et une ligne à la fin pour déplacer le log à la bonne place
file_ext_connues="${dossier_conf}/extConnues.txt"
## Création du fichier si il n'existe pas
[ -f "${file_ext_connues}" ] || > "${file_ext_connues}"
#dossier_orig
dossier_orig=""
#dossier_dest
dossier_dest=""
les_ext_connues=()
les_noms_dossiers=()
#**************************************************************************
#ETAGE JOURNAL
journal () {
local maintenant=$(date +%s.%N)
local difference=$(echo "${maintenant} - ${debut}" | bc)
echo -e "[${difference}] ${@}" >> "${fichier_log}"
}
#journal cumulé
[ -f "${fichier_log}" ] || > "${fichier_log}"
#on vide le log ou on le crée si il n'existe pas
# > "${fichier_log}"
journal "ouverture - $(date)"
journal "Ligne ${LINENO}--\t\t------------------------"
journal "Ligne ${LINENO}--\t\t\tchargement"
#**************************************************************************
#CHARGEMENT DES BASES
nettoyerFichier () {
journal "Ligne ${LINENO}--\t\t-> ${FUNCNAME[0]}"
# journal "Ligne ${LINENO}--\t\tArguments -> ${@}"
#range les lignes d'un fichier dans l'ordre alphabétique
sort -d -f -b -u "${@}" | tee "${@}.new" && mv "${@}.new" "${@}"
#supprime les lignes vides d'un fichier
sed -i '/^$/d' "${@}"
}
charger_ext_connues () {
journal "Ligne ${LINENO}--\t\t-> ${FUNCNAME[0]}"
# journal "Ligne ${LINENO}--\t\tArguments -> ${@}"
#Initialisation des bases
les_ext_connues=()
les_noms_dossiers=()
#Chargement des bases
local une_ligne
while IFS= read -r une_ligne
do
les_ext_connues+=( ${une_ligne%%;*} )
les_noms_dossiers+=( ${une_ligne##*;} )
done < "${file_ext_connues}"
}
nettoyerFichier "$file_ext_connues" >/dev/null
charger_ext_connues
journal "Ligne ${LINENO}--\t\tchargement"
#**************************************************************************
#Rangement par type Mine en cas de manque d'extension
getTYPE_MIME_FICHIER () {
journal "Ligne ${LINENO}--\t\t-> ${FUNCNAME[0]}"
# journal "Ligne ${LINENO}--\t\tArguments -> ${@}"
local chemin_fichier="$1"
local le_type_mime="$(file -b -i "${chemin_fichier}")"
if [ $? -eq 1 ]
then
journal "Ligne ${LINENO}--\t\t------------\nPROBLEME : \n${PWD} \n${chemin_fichier} \n${le_type_mime}\n-------------"
else
journal "Ligne ${LINENO}--\t\t${chemin_fichier} \n->${le_type_mime}"
type_mime_partie1="${le_type_mime%%; *}"
echo "${type_mime_partie1}"
fi
journal "Ligne ${LINENO}--\t\tfin du découpage TYPE_MIME"
}
rangerFichierParTypeMime () {
journal "Ligne ${LINENO}--\t\t-> ${FUNCNAME[0]}"
# journal "Ligne ${LINENO}--\t\tArguments -> ${@}"
local chemin_fichier="${@}"
local le_dossier="0_$(getTYPE_MIME_FICHIER "${@}" 1)"
journal "Ligne ${LINENO}--\t\tdéplacement de \n${chemin_fichier} \nvers \n${dossier_dest}/${le_dossier}"
deplacerFichier "${chemin_fichier}" "${dossier_dest}/${le_dossier}"
}
journal "Ligne ${LINENO}--\t\tchargement"
#**************************************************************************
deplacerFichier () {
journal "Ligne ${LINENO}--\t\t-> ${FUNCNAME[0]}"
# journal "Ligne ${LINENO}--\t\tArguments -> ${@}"
local unFichier
local uneDestination
unFichier="${1}"
uneDestination="${2}"
journal "Ligne ${LINENO}--\t\tunFichier : ${unFichier}"
journal "Ligne ${LINENO}--\t\tuneDestination : ${uneDestination}/"
[ -d "${uneDestination}" ] || mkdir -p "${uneDestination}" && \
journal "Ligne ${LINENO}--\t\tcréation dossier ${uneDestination} réussie"
mv "${unFichier}" "${uneDestination}/" && \
journal "Ligne ${LINENO}--\t\tdéplacement réussi" || \
journal "Ligne ${LINENO}--\t\tdéplacement échec"
}
journal "Ligne ${LINENO}--\t\tchargement"
#**************************************************************************
#ETAGE TRAITEMENT SELON EXTENSION
frm_EntryChoixType () {
journal "Ligne ${LINENO}--\t\t-> ${FUNCNAME[0]}"
# journal "Ligne ${LINENO}--\t\tArguments -> ${@}"
zenity --entry \
--title="Choisir un type" \
--text="l'extension ${@} n'a pas été trouvée ; \najouter aux motifs de type :" \
--entry-text=$(echo "${les_noms_dossiers[@]}" | tr ' ' '\n' | sort -u)
}
ajouterMotifExtension () {
journal "Ligne ${LINENO}--\t\t-> ${FUNCNAME[0]}"
# journal "Ligne ${LINENO}--\t\tArguments -> ${@}"
le_nouveau_dossier="$(frm_EntryChoixType "${1}")"
# if [ ${#le_nouveau_dossier} -gt 0 ]
# then
journal "Ligne ${LINENO}--\t\t# Ajouter aux extensions connues ${@};${le_nouveau_dossier}"
if [ ${#@} -ne 0 ] && [ ${#le_nouveau_dossier} -ne 0 ]
then
echo "${@};${le_nouveau_dossier}" | tee -a "${file_ext_connues}"
les_ext_connues+=( ${@} )
les_noms_dossiers+=( ${le_nouveau_dossier} )
else
return 1
fi
# else
journal "Ligne ${LINENO}--\t\tnewMotifExt = ${le_nouveau_dossier}" # TODO ?
# return 1
# fi
}
chercherExtdansDB () {
journal "Ligne ${LINENO}--\t\t-> ${FUNCNAME[0]}"
# journal "Ligne ${LINENO}--\t\tArguments -> ${@}"
# recherche dans les extensions connues
# renvoie un dossier si trouvé sinon rien
local leTest="${@}" # c'est l'extension à tester
journal "Ligne ${LINENO}--\t\t#les_ext_connues : ${#les_ext_connues[@]}"
for (( c=0;c<${#les_ext_connues[@]};c++ ))
do
# journal "Ligne ${LINENO}--\t\t${leTest} == ${les_ext_connues[$c]} ?"
if [ "${leTest}" = "${les_ext_connues[$c]}" ]
then
journal "Ligne ${LINENO}--\t\tOUI extension trouvée : ${les_noms_dossiers[$c]}"
echo "${les_noms_dossiers[$c]}"
break
# else
# journal "Ligne ${LINENO}--\t\tNON"
fi
done
}
rangerFichiersParExtension () {
journal "Ligne ${LINENO}--\t\t-> ${FUNCNAME[0]}"
# journal "Ligne ${LINENO}--\t\tArguments -> ${@}"
chemin_fichier="${@}" ;
nom_fichier="${chemin_fichier##*/}"
ext_fichier="${nom_fichier##*.}"
local un_chemin="$(chercherExtdansDB "${ext_fichier}")"
journal "Ligne ${LINENO}--\t\tun_chemin : ${un_chemin}"
if [ "${#un_chemin}" -eq 0 ]
then
journal "Ligne ${LINENO}--\t\textension inconnue"
local un_nouveau_dossier="$(ajouterMotifExtension "${ext_fichier}")"
if [ ! ${#un_nouveau_dossier} -eq 0 ]
then
un_nouveau_dossier="${un_nouveau_dossier##*;}"
deplacerFichier "${chemin_fichier}" "${dossier_dest}/${un_nouveau_dossier}"
nettoyerFichier "$file_ext_connues" >/dev/null
charger_ext_connues
else
journal "Ligne ${LINENO}--\t\tl'extension ne sera pas ajoutée"
fi
else
journal "Ligne ${LINENO}--\t\tDéplacement du fichier selon extension"
deplacerFichier "${chemin_fichier}" "${dossier_dest}/${un_chemin[$c]}"
fi
}
traiterFichier () {
journal "Ligne ${LINENO}--\t\t----------------------------------"
journal "Ligne ${LINENO}--\t\t-> ${FUNCNAME[0]}"
# journal "Ligne ${LINENO}--\t\tArguments -> ${@}"
chemin_fichier="$(readlink -f "${@}")"
nom_fichier="${chemin_fichier##*/}"
ext_fichier="${nom_fichier##*.}"
if [ "${ext_fichier}" = "${nom_fichier}" ]
then
journal "Ligne ${LINENO}--\t\t-------------pas d'extension !-------------"
rangerFichierParTypeMime "${chemin_fichier}"
else
journal "Ligne ${LINENO}--\t\tl'extension est ${ext_fichier}"
rangerFichiersParExtension "${chemin_fichier}"
fi
}
journal "Ligne ${LINENO}--\t\tchargement"
#**************************************************************************
#Etage traitement des arguments du script
setdossier_dest () {
journal "Ligne ${LINENO}--\t\t-> ${FUNCNAME[0]}"
# journal "Ligne ${LINENO}--\t\tArguments -> ${@}"
dossier_dest="${dossier_orig}"
}
estLienDossierFichier () {
journal "Ligne ${LINENO}--\t\t-> ${FUNCNAME[0]}"
# journal "Ligne ${LINENO}--\t\tArguments -> ${@}"
if [ -L "${@}" ]
then
journal "error : ${@} est un lien"
else
if [ -d "${@}" ]
then
journal "error : ${@} est un dossier"
else
if [ -f "${@}" ]
then
# dossier_orig="${@}"
dossier_orig="${@%/*}"
setdossier_dest
traiterFichier "${@}"
fi
fi
fi
}
traiterLesArguments () {
journal "Ligne ${LINENO}--\t\t-> ${FUNCNAME[0]}"
# journal "Ligne ${LINENO}--\t\tArguments -> ${@}"
IFS=$'\n'
local url
for url in ${@}
do
journal "---------------------------------------------"
journal "Ligne ${LINENO}--\t\turl : ${url}"
estLienDossierFichier "${url}"
done
}
selectionnerTousLesFichiers () {
journal "Ligne ${LINENO}--\t\t-> ${FUNCNAME[0]}"
for un_fichier in *
do
if [ -e "$(readlink -f "${un_fichier}")" ]
then
estLienDossierFichier "$(readlink -f "${un_fichier}")"
else
journal "erreur avec ${un_fichier}"
fi
done
}
afficher_ExtConnues () {
journal "Ligne ${LINENO}--\t\t-> ${FUNCNAME[0]}"
cat "${file_ext_connues}"
echo -e "le fichier est : ${file_ext_connues}"
exit 66
}
afficher_fichier_log () {
cat "${fichier_log}"
echo -e "le fichier est : ${fichier_log}"
exit 67
}
vider_fichier_log () {
>"${fichier_log}"
echo -e "le fichier est vidé : \n${fichier_log}"
exit 67
}
afficher_aide () {
cat <<EOF
dorian va nous aider à ranger nos fichiers
lancez dorian [Ff:hHvVcl]
dorian -h ou -H
cette aide
dorian -v ou -V
la version de ce script
dorian -F
range tous les fichiers trouvés dans le répertoire courant
dorian -f 'un Fichier'
range 'un Fichier' mettre -f pour chaque fichier
dorian "/un/fichier/ici" "/un/fichier/la"
liste de fichiers séparés par des sauts de ligne ou des espaces
dorian -c
affiche le fichier des extentions de l'utilisateur courant et son emplacement.
dorian -l
affiche le fichier log de l'utilisateur courant et son emplacement.
EOF
afficher_version
}
afficher_version () {
echo "$0 version : $version_logiciel"
}
traiterLesOptions () {
journal "Ligne ${LINENO}--\t\t-> ${FUNCNAME[0]}"
while getopts cFf:hHlvV option # : pour dire que l'option attend un argument
do
case "${option}" in
c ) afficher_ExtConnues ;;
F ) selectionnerTousLesFichiers ;;
f ) [ -e "$(readlink -f "${OPTARG}")" ] && estLienDossierFichier "$(readlink -f "${OPTARG}")" ;;
h | H ) afficher_aide ;;
l ) afficher_fichier_log ;;
L ) vider_fichier_log ;;
v | V ) afficher_version ;;
esac
done
shift $(($OPTIND-1))
[ -n $1 ] && journal "Ligne ${LINENO}--\t\tje n'ai pas traité cela : ${@}"
}
voirArguments () {
journal "Ligne ${LINENO}--\t\t-> ${FUNCNAME[0]}"
if [ ! ${#@} -eq 0 ]
then
journal "Ligne ${LINENO}--\t\tNbre d'arguments trouvés : ${#@}"
case ${@} in
-* ) traiterLesOptions "${@}" ;;
*) traiterLesArguments "${@}" ;;
esac
else
journal "Ligne ${LINENO}--\t\tpas d'arguments trouvés"
afficher_aide
echo "erreur 65 ; arguments manquants"
exit 65
fi
}
journal "Ligne ${LINENO}--\t\tchargement"
#**************************************************************************
# nautilus "${PWD}"
# nautilus "$HOME/.config/kholo/dorian"
# exit 0
IFS=$'\n'
voirArguments ${@}
journal "---------------------------------------------
Ligne ${LINENO}--\t\tfermeture"
#**************************************************************************
## je met le log dans le dossier personnel de l’utilisateur
[ -f "${dossier_conf}/${nom_logiciel}.log" ] || touch "${dossier_conf}/${nom_logiciel}.log"
cat "${fichier_log}" >> "${dossier_conf}/${nom_logiciel}.log"
exit 0
Dernière modification par kholo (Le 25/05/2020, à 16:57)
Hors ligne
#3 Le 22/05/2020, à 12:54
- kholo
Re : [TUTO Bash] rangement automatique fichiers par extension
édit du 22 mai 2020...
si vous suiviez ce fil, je met les deux premiers posts à jour...
juste à suivre les infos... façon fécomsa
je me garde ce post ci pour y mettre les autres navigateurs de fichiers plus tard...
à suivre !
Hors ligne
#4 Le 22/05/2020, à 13:28
- Watael
Re : [TUTO Bash] rangement automatique fichiers par extension
salut,
les noms des variables doivent ne pas être tout en majuscules.
les accolades dans le développement de paramètres sont inutiles s'ils ne protègent pas d'une concaténation, ou n'indiquent pas une substitution. c'est pourquoi leur utilisation systématique est "nuisible".
for ligne in $(cat fichier) ->while read ligne; do : ...; done <fichier
les guillemets sont facultatifs entre double-crochets.
== est à réserver aux double-crochets.
et je n'ai pas l'impression que tu utilises de fonctionnalités avancées des double-crochets; leur emploi est alors inutile.
il faut mettre des guillemets autour de $@ pour éviter les découpage en mots et respecter le parcours des éléments d'un tableau (oui, $@ est un tableau).
et s'il y a des fichiers qui portent le même nom ?
Connected \o/
Welcome to sHell. · eval is evil.
Hors ligne
#5 Le 25/05/2020, à 19:04
- kholo
Re : [TUTO Bash] rangement automatique fichiers par extension
salut,
Bonjour Maître Jedi Watael... toujours content que tu prennes un peu de temps pour te pencher sur une de mes élucubrations !
les noms des variables doivent ne pas être tout en majuscules.
ça ok... pas de soucis... j'ai repris... j'y reviendrais pour qu'elles soient un peu plus lisibles
les accolades dans le développement de paramètres sont inutiles s'ils ne protègent pas d'une concaténation, ou n'indiquent pas une substitution. c'est pourquoi leur utilisation systématique est "nuisible".
là c'est plus compliqué pour moi... j'ai fait ça moi ?
alors attends j'essaie déjà de comprendre...
le développement de paramètres dans l'appelle d'une fonction ?
par exemple :
parametre="blabla"
ma_fonction(){
#une fonction qui fait des trucs
echo "je suis une fonction"
}
ma_fonction $parametre
et non pas :
ma_fonction ${parametre}
je pensais plus à l’esthétisme, la facilité de lecture voire la sécurité d'une façon générale...
mais une règle liée à la protection lors de concaténation... et que cela puisse avoir un côté "nuisible"...
... bon je vais y cogiter... je n'y ai pas touché encore...
for ligne in $(cat fichier) ->while read ligne; do : ...; done <fichier
oui... ouiiii... j'ai quand même dû tatonner un peu et rezieuter des exemples contrairement à la lecture dans le cat que je sort plus intuitivement...
j'arrive à ça :
charger_ext_connues () {
les_ext_connues=()
les_noms_dossiers=()
local une_ligne
while IFS= read -r une_ligne
do
les_ext_connues+=( ${une_ligne%%;*} )
les_noms_dossiers+=( ${une_ligne##*;} )
done < "${file_ext_connues}"
}
mais tripoter à IFS semble masturbatoire !
while read -r une_ligne
do
les_ext_connues+=( ${une_ligne%%;*} )
les_noms_dossiers+=( ${une_ligne##*;} )
done < "${file_ext_connues}"
par contre le -r ne me semble pas facultatif...
... et en parlant de ça, j'ai jamais pigé :
kiki@Sat-L500:~$ man read
kiki@Sat-L500:~$ info read
READ(2) Linux Programmer's Manual READ(2)
NAME
read - read from a file descriptor
SYNOPSIS
#include <unistd.h>
ssize_t read(int fd, void *buf, size_t count);
DESCRIPTION
read() attempts to read up to count bytes from file descriptor fd into
the buffer starting at buf.
On files that support seeking, the read operation commences at the cur‐
rent file offset, and the file offset is incremented by the number of
bytes read. If the current file offset is at or past the end of file,
no bytes are read, and read() returns zero.
If count is zero, read() may detect the errors described below. In the
absence of any errors, or if read() does not check for errors, a read()
with a count of 0 returns zero and has no other effects.
If count is greater than SSIZE_MAX, the result is unspecified.
RETURN VALUE
On success, the number of bytes read is returned (zero indicates end of
file), and the file position is advanced by this number. It is not an
error if this number is smaller than the number of bytes requested;
this may happen for example because fewer bytes are actually available
right now (maybe because we were close to end-of-file, or because we
are reading from a pipe, or from a terminal), or because read() was
interrupted by a signal. See also NOTES.
On error, -1 is returned, and errno is set appropriately. In this
case, it is left unspecified whether the file position (if any)
changes.
ERRORS
EAGAIN The file descriptor fd refers to a file other than a socket and
has been marked nonblocking (O_NONBLOCK), and the read would
block. See open(2) for further details on the O_NONBLOCK flag.
EAGAIN or EWOULDBLOCK
The file descriptor fd refers to a socket and has been marked
nonblocking (O_NONBLOCK), and the read would block.
POSIX.1-2001 allows either error to be returned for this case,
and does not require these constants to have the same value, so
a portable application should check for both possibilities.
EBADF fd is not a valid file descriptor or is not open for reading.
EFAULT buf is outside your accessible address space.
EINTR The call was interrupted by a signal before any data was read;
see signal(7).
EINVAL fd is attached to an object which is unsuitable for reading; or
the file was opened with the O_DIRECT flag, and either the
address specified in buf, the value specified in count, or the
current file offset is not suitably aligned.
EINVAL fd was created via a call to timerfd_create(2) and the wrong
size buffer was given to read(); see timerfd_create(2) for fur‐
ther information.
EIO I/O error. This will happen for example when the process is in
a background process group, tries to read from its controlling
terminal, and either it is ignoring or blocking SIGTTIN or its
process group is orphaned. It may also occur when there is a
low-level I/O error while reading from a disk or tape.
EISDIR fd refers to a directory.
Other errors may occur, depending on the object connected to fd. POSIX
allows a read() that is interrupted after reading some data to return
-1 (with errno set to EINTR) or to return the number of bytes already
read.
CONFORMING TO
SVr4, 4.3BSD, POSIX.1-2001.
NOTES
On Linux, read() (and similar system calls) will transfer at most
0x7ffff000 (2,147,479,552) bytes, returning the number of bytes actu‐
ally transferred. (This is true on both 32-bit and 64-bit systems.)
On NFS filesystems, reading small amounts of data will update the time‐
stamp only the first time, subsequent calls may not do so. This is
caused by client side attribute caching, because most if not all NFS
clients leave st_atime (last file access time) updates to the server,
and client side reads satisfied from the client's cache will not cause
st_atime updates on the server as there are no server-side reads. UNIX
semantics can be obtained by disabling client-side attribute caching,
but in most situations this will substantially increase server load and
decrease performance.
BUGS
According to POSIX.1-2008/SUSv4 Section XSI 2.9.7 ("Thread Interactions
with Regular File Operations"):
All of the following functions shall be atomic with respect to each
other in the effects specified in POSIX.1-2008 when they operate on
regular files or symbolic links: ...
Among the APIs subsequently listed are read() and readv(2). And among
the effects that should be atomic across threads (and processes) are
updates of the file offset. However, on Linux before version 3.14,
this was not the case: if two processes that share an open file
description (see open(2)) perform a read() (or readv(2)) at the same
time, then the I/O operations were not atomic with respect updating the
file offset, with the result that the reads in the two processes might
(incorrectly) overlap in the blocks of data that they obtained. This
problem was fixed in Linux 3.14.
SEE ALSO
close(2), fcntl(2), ioctl(2), lseek(2), open(2), pread(2), readdir(2),
readlink(2), readv(2), select(2), write(2), fread(3)
COLOPHON
This page is part of release 4.04 of the Linux man-pages project. A
description of the project, information about reporting bugs, and the
latest version of this page, can be found at
http://www.kernel.org/doc/man-pages/.
Linux 2015-07-23 READ(2)
pourtant je francise le man en post install... bon ça c'est pas trop un problème... mais on parle bien de read là ?
et help est très limité...
kiki@Sat-L500:~$ read -H
bash: read: -H : option non valable
read : utilisation : read [-ers] [-a tableau] [-d delim] [-i texte] [-n nchars] [-N nchars] [-p prompt] [-t timeout] [-u fd] [nom ...]
kiki@Sat-L500:~$ read --help
bash: read: -- : option non valable
read : utilisation : read [-ers] [-a tableau] [-d delim] [-i texte] [-n nchars] [-N nchars] [-p prompt] [-t timeout] [-u fd] [nom ...]
les guillemets sont facultatifs entre double-crochets.
== est à réserver aux double-crochets.
et je n'ai pas l'impression que tu utilises de fonctionnalités avancées des double-crochets; leur emploi est alors inutile.
Donc, oui... j'ai tout repassé en simple crochet et supprimer un double == qui traînait... certainement un reste de mes cours de python lol
Par contre... tu m'intéresses... j'ai l'impression que tu as affiné ta compréhension de l'utilisation des simples et doubles crochets... sans doute depuis pas mal de temps maintenant mais ça faisait un moment que je ne t'avais pas croisé et j'ai eu l'impression lors de l'écriture de ma page sur le bash que tu étais encore un peu incertain là dessus... des nouveautés ? le man de test à évolué ?
il faut mettre des guillemets autour de $@ pour éviter les découpages en mots et respecter le parcours des éléments d'un tableau (oui, $@ est un tableau).
Bon là c'est plus simple si c'est une règle unique et immuable !
on dit quoi alors ? $@ => "$@"... pour le parcours d'un tableau... ok ça j'avais bien pigé mais justement je jongle un peu et j'avais même pris l'habitude de ne pas les mettre...
je m'explique :
je te résume : je crée deux listes et des facons différentes de les itérer par deux avec et sans les guillemets
la première liste et les deux premiers exemples sont sans intéret...
#!/bin/bash
# ----------------------------------------------
# test bash et guillemets dans tableaux
# ----------------------------------------------
une_liste="un deux trois cat"
ligne="==========================="
echo "façon 1"
for une_ligne in $une_liste
do
echo $une_ligne
done
echo "$ligne"
echo "façon 2"
for une_ligne in "$une_liste"
do
echo $une_ligne
done
echo "$ligne"
jusque là facile et même sans intéret
façon 1
un
deux
trois
cat
===========================
façon 2
un deux trois cat
===========================
voilà pour l'introduction plus que basique...
mais, si je passe à la ligne, je met plusieurs mots sur une ligne, je saute même une ligne histoire de compliquer un peu le truc...
une_liste="un
deux
trois
cat le chat
et quinte"
# l'espace avant cette ligne est exprès !
echo "façon 3"
for une_ligne in $une_liste
do
echo $une_ligne
done
echo "$ligne"
echo "façon 4"
for une_ligne in "$une_liste"
do
echo $une_ligne
done
echo "$ligne"
là tout est dans les choux... mais c'est normal puisque je ne suis aucune règle d'écriture !
façon 3
un
deux
trois
cat
le
chat
et
quinte
===========================
façon 4
un deux trois cat le chat et quinte
===========================
jusqu'à présent j'ai écrit du code de sagouin... on est d'accord....
mais :
echo "façon 5"
IFS=$'\n'
for une_ligne in "${une_liste[@]}"
do
echo $une_ligne
done
echo "$ligne"
echo "façon 6"
for une_ligne in ${une_liste[@]}
do
echo $une_ligne
done
echo "$ligne"
façon 5
un deux trois cat le chat et quinte
===========================
façon 6
un
deux
trois
cat le chat
et quinte
===========================
et façon 6 en général est ce que je cherche... éclater une liste en ligne ...
Tout cela pour t'expliquer pourquoi je ne quotte plus mes variables en tableau quand je veux les itérer...
et là tu me dis : "oui mais avec $@ on met les doubles quottes... c'est ça ?"
... parce que, moi, j'avis cru comprendre le contraire...
et comme j'ai un petit pois en guise de cerveau... je retest à chaque fois... et j'en reviens toujours à cette façon d'écrire mes itérations en bash...
et quand je dis que je suis un con, ce n'est pas un euphémisme...
tu te doutes de ce que j'ai fait !!! ... et du résultat ?
parce que moi avant de faire le test, j'aurais été parfaitement incapable de dire pourquoi et comment on arrive à ce genre de sortie...
parlons en, si tu veux bien :
#!/bin/bash
# ----------------------------------------------
# test bash et guillemets dans tableaux
# ----------------------------------------------
ligne="==========================="
une_liste="un
deux
trois
cat le chat
et quinte"
fonction_de_la_mort(){
IFS=$'\n'
for une_ligne in "${@}"
do
echo $une_ligne
done
}
fonction_de_la_muerte(){
IFS=$'\n'
for une_ligne in ${@}
do
echo $une_ligne
done
}
echo "façon 7"
fonction_de_la_mort "$une_liste"
echo "$ligne"
echo "façon 8"
fonction_de_la_mort $une_liste
echo "$ligne"
echo "façon 9"
fonction_de_la_muerte "$une_liste"
echo "$ligne"
echo "façon 10"
fonction_de_la_muerte $une_liste
echo "$ligne"
la 7 est dans les choux et les trois autres tiennent tout juste la route...
(puisque dans aucune je ne retrouve mon fameux saut de ligne)
donc la sortie :
façon 7
un deux trois cat le chat et quinte
===========================
façon 8
un
deux
trois
cat le chat
et quinte
===========================
façon 9
un
deux
trois
cat le chat
et quinte
===========================
façon 10
un
deux
trois
cat le chat
et quinte
===========================
et bien sûr, j'ai fait sans toucher à IFS mais on passe en coupure avec les trois séparateurs : espaces / tab / saut de ligne
... si je me rappelle encore de mon mooc de bash...
... et donc, comme c'était trop capillotracté pour moi, j'avais retenue une règle : ne jamais quotter pour itérer sur les tableaux...
mais j'ai encore dû comprendre un truc de travers...
et s'il y a des fichiers qui portent le même nom ?
Alors oui, en effet, je n'ai pas envisagé cette éventualité car, je pensais que ce genre de script est plutôt à utiliser quand on laisse s'entasser des centaines ou milliers de fichiers dans un dossier que l'on veut dispatcher vite fait avant de les traiter après coup...
... je ne sais pas si je m'explique bien...
c'est vrai qu'on est susceptible de se retrouver avec des doublons si nos dossiers sont déjà créés et qu'on ajoute après coup d'autres fichiers que l'on organise dans une seconde passe (ou x ième passe d'ailleurs)... genre utilisation du dossier magique... tu me donnes des idées là !
donc je vais ajouter une routine pour gérer les doublons éventuels... bien vu...
merci de ton assiduité et ta patience Watael
Hors ligne
#6 Le 25/05/2020, à 19:34
- Watael
Re : [TUTO Bash] rangement automatique fichiers par extension
ouf! tout ça, tout ça !?
pour les accolades, c'est ça. Elles surchargent le code sans rien indiqué, et sont donc inutiles. Quand je vois des accolades, j'attends un Substitution de paramètres ("${var//correspondance/remplacment}", par exemple).
N'oublie pas les guillemets que toujours tu mettras autour des Développements de paramètres. TOUJOURS*; à moins de savoir pourquoi.
read -r je suis le grand coupable : je l'oublie tout le temps. c'est ma faute. je n'ai pas l'occasion d'être confronté aux problèmes que ça peut poser, alors ce n'est pas automatique.
il n'y a pas de man ou d'info concernant la commande interne du shell read, il faut ouvrir la page man de bash, ou taper help read pour accéder à sa description.
pour les différents tests, ça n'a pas changé; c'est probablement moi qui ait précisé ma pensée à l'usage... si j'ai seulement un clou à enfoncer, pourquoi utiliserais-je un marteau de charpentier, qui comporte un arrache-clous ?
un test simple appelle un simple test.
uneListe="un deux trois" n'est pas une liste, c'est une variable "plate", en effet, pour itérer "dessus" il faut ne pas mettre de guillemets (ça fait partie du "à moins de savoir pourquoi").
uneListe=( un deux "trois quatre" ), ça, c'est une liste, et si tu ne mets pas de guillemets, trois et quatre apparaîtront comme des éléments différents, alors qu'ils ne sont qu'un seul élément.
j'en ai oublié ?
--
* c'est valable pour les tableaux et pour $@.
Connected \o/
Welcome to sHell. · eval is evil.
Hors ligne
#7 Le 25/05/2020, à 21:26
- marcus68
Re : [TUTO Bash] rangement automatique fichiers par extension
Bonjour,
La tâche initiale (classer des fichiers selon leurs extensions) peut être réalisée en genre 3 commandes, quel intérêt de faire tout ça ?
Pourquoi créer un dossier bin alors qu'un dossier est dédié à cette usage (.local/bin) et parfaitement intégré à la variable PATH ?
Pourquoi tu finis avec exit 0 ? Tu fais un mix avec un autre langage de programmation ?
Cordialement
Hors ligne
#8 Le 26/05/2020, à 00:05
- MicP
Re : [TUTO Bash] rangement automatique fichiers par extension
Bonjour marcus68
… Pourquoi créer un dossier bin alors qu'un dossier est dédié à cette usage (.local/bin) et parfaitement intégré à la variable PATH ? …
Ci-dessous, un extrait du fichier ~/.profile
d'un compte utilisateur non root sur debian comme sur Ubuntu :
# set PATH so it includes user's private bin if it exists
if [ -d "$HOME/bin" ] ; then
PATH="$HOME/bin:$PATH"
fi
Une traduction (approximative) du commentaire précédant ces quelques lignes de commande :
# définir PATH pour qu'il inclue le répertoire bin privé de l'utilisateur s'il existe
Hors ligne
#9 Le 26/05/2020, à 00:17
- kholo
Re : [TUTO Bash] rangement automatique fichiers par extension
@Watael : je te le fais court : merci !!!
Bonjour,
La tâche initiale (classer des fichiers selon leurs extensions) peut être réalisée en genre 3 commandes, quel intérêt de faire tout ça ?
Pourquoi créer un dossier bin alors qu'un dossier est dédié à cette usage (.local/bin) et parfaitement intégré à la variable PATH ?
Pourquoi tu finis avec exit 0 ? Tu fais un mix avec un autre langage de programmation ?
Cordialement
alors tout cela s'inscrit dans un ensemble de scripts que j'utilise et que je laisse utilisé à des client.e.s et à des ami.e.s...
je suis pour que le plus grand nombre aient accès à la ligne de commande et les scripts et avant eux les nautilus scripts sont une très bonne école...
mais il faut que ce soit un peu plus simple que de la ligne de commande...
donc je les relie aux nautilius scripts pour faire du clic world !
c'est un peu carrossé comme une voiture de course justement parce que j'aime bien l'idée qu'on puisse voir le moteur !
donc 3 lignes dis tu ?
avec un fichier qui associerait les extensions avec un nom pour la création d'un dossier...
elles risquent de devenir bien longues tes lignes mais je ne demande qu'à voir...
ou les jpg dans un dossier jpg et les jpeg dans un dossier jpeg... non ?
enfin, justement ce n'est pas ce que je voulais faire...
pourquoi je crée un dossier bin dans le dossier personnel ?
encore une fois, j'aime bien qu'on puisse voir le moteur...
mais la réponse se trouve par défaut dans le fichier .profile de chaque utilisateur :
# set PATH so it includes user's private bin directories
PATH="$HOME/bin:$HOME/.local/bin:$PATH"
et ce n'est pas moi mais Canonical (ou Debian... ou c'est encore plus général que ça ?!) qui l'y a mis !
On manque cruellement de normes "normalisées" en Linux... c'est à cause de la retro compatibilité je pense !
j'ai du mal à comprendre pourquoi les anciens dossiers ne disparaissent pas au profit de liens symboliques...
ça serait un signal fort... et, en plus, je croyais bien me souvenir que la création du PATH était soumise à condition...
ça doit être ailleurs...
... en cherchant pour te répondre, j'ai retrouvé ce que je m'attendais à trouver :
# set PATH so it includes user's private bin if it exists
if [ -d "$HOME/bin" ] ; then
PATH="$HOME/bin:$PATH"
fi
mais plus dans le mien...
... ah... et je vois le commentaire de MicP qui confirme alors même que je te répond
merci MicP
quant au exit 0 ?! ...
ah oui ce exit 0 est un reste de mes débuts en bash
non pas que j'ai beaucoup évolué mais ça commence à faire quelques années que je m'amuse à coder...
... c'est quand même plus évolué que du temps où je faisais du batch
Dernière modification par kholo (Le 26/05/2020, à 00:19)
Hors ligne
#10 Le 26/05/2020, à 06:02
- marcus68
Re : [TUTO Bash] rangement automatique fichiers par extension
donc 3 lignes dis tu ?
avec un fichier qui associerait les extensions avec un nom pour la création d'un dossier...
elles risquent de devenir bien longues tes lignes mais je ne demande qu'à voir...
ou les jpg dans un dossier jpg et les jpeg dans un dossier jpeg... non ?
enfin, justement ce n'est pas ce que je voulais faire...
non pas 3 lignes, 3 commandes. Un exemple en 4 commandes (avec le fichier extConnues.txt dans le dossier ~/.config/kholo/dorian) :
#!/bin/bash
dossier_conf="~/.config/kholo/dorian"
IFS=";"
while read extension dossier
do
test -d "$dossier"||mkdir "$dossier"
mv *.$extension "$dossier"
done < "$dossier_conf/extConnues.txt"
Dernière modification par marcus68 (Le 26/05/2020, à 06:04)
Hors ligne
#11 Le 26/05/2020, à 06:36
- marcus68
Re : [TUTO Bash] rangement automatique fichiers par extension
bah je sais que ça fait longtemps que tu codes, mais là c'est inquiétant.
- Tu fais une fonction qui renvoie du texte, et les fois où elle est utilisé tu rediriges le texte vers /dev/null ?
nettoyerFichier "$file_ext_connues" >/dev/null
- Tu définies des variables nulles en début du code :
dossier_orig=""
- Tu utilises des options inutiles :
exemple ( -e sans intérêt dans a peu près tous les echo)
echo -e "le fichier est : ${fichier_log}"
Hors ligne
#12 Le 26/05/2020, à 07:48
- bruno
Re : [TUTO Bash] rangement automatique fichiers par extension
en #10
- le dossier est créé même s'il n'y a aucun fichier à déplacer ;
- le fichier est écrasé si un fichier de même nom existe déjà ;
- redéfinir globalement IFS risque de poser problème.
#13 Le 26/05/2020, à 15:33
- kholo
Re : [TUTO Bash] rangement automatique fichiers par extension
Bon, je prends toutes vos remarques en considération...
Pour la petite histoire :
Je rappel que mon idée n'est pas nouvelle et se basait sur un autre travail nommé dossier magique (rendons à César !) dont je parle à Watael dans ce fil et je comptais à terme améliorer et mettre au goût du jour la doc...
je vois quelques utilisations majeures à ce script :
le rangement automatique suite à un photorec
les kikoolol qui entassent les fichiers dans le dossier "téléchargement"
ceux qui sont aussi bordéliques que moi
...
et justement, en y réfléchissant, je me suis dit que tout le monde et toutes les circonstances ne justifiaient pas les mêmes types de rangements... d'où mon idée de partir d'un fichier qui associerait extensions et noms de dossiers... association qui pourrait être choisit par la suite...
et que tous les utilisateurs n'auraient pas la connaissance pour tenir le fichier d'association (et une faute de frappe est si vite arrivée) d'où une routine qui fait les ajouts... et trie les lignes...
mais on arrive à la fin de tout cela car l'IA fera cela certainement bien mieux que n'importe quel script... et j'ai "peur" qu'on aille vers la fin des fichiers (vus par l'utilisateur final bien sûr).
Comme je vois que pas mal d'entre vous ont les capacités pourquoi ne pas repartir sur ce script et surtout qu'il fait parti de la doc, qu'il date de 2007 et était encore utilisé au moins en 2017... et comme la doc est un peu plus volatile que ce forum, je met le script tel qu'il est à ce jour avec les premières corrections pour en garder une trace :
#!/bin/bash
current_ver=1.1.1
# modifications / version 1.1
# variables en minuscules modifiées pour être facilement retrouvées
# "function" supprimé des fonctions
# accolade ouvrante des fonctions sur la même ligne que le nom de la fonction
# plus de tabulations remplacées par des espaces
# `fonction` remplacés par $(fonction)
# initialisation des options
en_terminal="est_faux"
en_aide="est_faux"
en_version="est_faux"
en_recursif="est_faux"
# Définition des fonctions du script
# Test du code retour de zenity :
testcrd(){
if [ ${crd} = -1 ]; then
zenity --error --title "Dossier Magique" --text "Une erreur inattendue s'est produite. Abandon."
exit 2
fi
if [ ${crd} = 1 ]; then
zenity --info --title "Dossier Magique" --text "Vous avez choisi d'annuler le script. Sortie."
exit 1
fi
return 0
}
# Déplacement d'un fichier et mise à jour du fichier log :
bouge(){
mv "${1}" "${2}"
heure=$(date +%D-%H:%m)
echo "[${heure}] "${1}" déplacé dans "${2}"" >> ${LOG}
return 0
}
# Créons les répertoires s'ils n'existent pas :
createdirs(){
mkdir -p "${fTXT}"
mkdir -p "${fPDF}"
mkdir -p "${fAUDIO}"
mkdir -p "${fVIDEO}"
mkdir -p "${fIMG}"
mkdir -p "${fARCHIVES}"
mkdir -p "${fDOCS}"
mkdir -p "${fTEX}"
mkdir -p "${fMISC}"
mkdir -p "${fBIN}"
return 0
}
# Trions les fichiers :
tri(){
cd "${1}"
# Faut-il gérer la récursivité pour les sources ?
if [[ "${en_recursif}" = "est_vrai" && "${dir_base}" != "${1}" ]]
then
crd=0
while [ ${crd} = 0 ]
do
ls -d */ 2> /dev/null > /tmp/tri
crd=$?
while read dossier
do
# On remonte tout le dossier d'un niveau
mv -t "./" "${dossier}"* 2> /dev/null
# Puis on supprime le dossier vide
rmdir "${dossier}"
done < /tmp/tri
done
fi
ls > /tmp/tri
while read fichier
do
# Cas particulier des fichiers à traiter d'après l'extension
type="${fichier##*.}"
case "${type}" in
wma) bouge "${fichier}" "${fAUDIO}";;
*) # Utilisons si possible le type mime :
type=$(file -bi "${fichier}")
case "${type}" in
*script*) bouge "${fichier}" "${fBIN}";;
*executable*) bouge "${fichier}" "${fBIN}";;
*pdf* | *dvi* | *postscript*) bouge "${fichier}" "${fPDF}";;
*audio* | *ogg*) bouge "${fichier}" "${fAUDIO}";;
*video* | *flash*) bouge "${fichier}" "${fVIDEO}";;
*image*) bouge "${fichier}" "${fIMG}";;
*tar* | *rar* | *zip*) bouge "${fichier}" "${fARCHIVES}";;
*msword* | *excel* | *powerpoint* | *rtf* | *opendocument*) bouge "${fichier}" "${fDOCS}";;
*) # Si le type mime ne suffit pas :
type=$(file -b "${fichier}")
case "${type}" in
*directory*) continue;;
*byte-compiled*) bouge "${fichier}" "${fBIN}";;
*script*) bouge "${fichier}" "${fBIN}";;
*LaTeX*) bouge "${fichier}" "${fTEX}";;
*ASF*) bouge "${fichier}" "${fVIDEO}";;
*text*) bouge "${fichier}" "${fTXT}";;
*) # Le type est donc inconnu :
bouge "${fichier}" "${fMISC}";;
esac
;;
esac
;;
esac
done < /tmp/tri
return 0
}
# Testons d'abord si le script est lancé en mode terminal
while getopts ":agrtv-:" OPT
do
# gestion des options longues avec ou sans argument
[ $OPT = "-" ] && case "${OPTARG%%=*}" in
aide) OPT="a" ;;
graphique) OPT="g" ;;
recursif) OPT="r";;
terminal) OPT="t" ;;
version) OPT="v" ;;
*) echo "Option inconnue" ; exit 1 ;;
esac
# puis gestion des options courtes
case $OPT in
a) en_aide="est_vrai" ;;
g) en_terminal="est_faux" ;;
r) en_recursif="est_vrai";;
t) en_terminal="est_vrai" ;;
v) en_version="est_vrai" ;;
*) echo "Option inconnue" ; exit 1 ;;
esac
done
# Aide
if [ "$en_aide" = "est_vrai" ]
then
echo "Syntaxe 1 : avec 0 ou 1 option et sans paramètre."
echo " $0 Mode graphique."
echo " $0 -g | --graphique Mode graphique."
echo " $0 -a | --aide Affiche l'aide."
echo " $0 -v | --version Affiche la version."
echo " $0 -r | --recursif Gére la récursivité."
echo "Syntaxe 2 : en mode terminal avec paramètre(s) obligatoire(s)."
echo " $0 -t | --terminal CIBLE [SOURCE1 ... SOURCEn]"
echo " où CIBLE est le dossier résultant classé"
echo " et SOURCE(s) le(s) dossier(s) vrac à trier."
echo " Si SOURCE est omis, alors CIBLE=SOURCE."
exit 0
fi
# Version
if [ "$en_version" = "est_vrai" ]
then
echo " "
echo "Version $0 : $current_ver"
# head -15 $0 | grep -v bash
exit 0
fi
# Mémorisons le répertoire courant
old_dir_base=$(pwd)
# Initialisons le dossier racine CIBLE
dir_base="${HOME}"
# Définissons le fichier de log (aucun par défaut)
LOG="/dev/null"
# Option "terminal" pour utilisation non graphique
if [ "$en_terminal" = "est_vrai" ]
then
# On élimine les options pour charger le(s) paramètre(s)
while [ "${1:0:1}" = "-" ]
do
shift
done
if [ "${1}" = "" ]
then
echo "En mode terminal, indiquer obligatoirement le(s) paramètre(s)"
exit 1
fi
# Sinon, exécution en mode graphique
else
# On affiche d'abord une fenêtre d'aide à l'utilisateur
echo "- Vous allez tout d'abord choisir le dossier dans lequel seront créés" > /tmp/notice
echo " les sous-dossiers où classer les fichiers triés. C'est le dossier CIBLE." >> /tmp/notice
echo "- Vous sélectionnerez ensuite le(s) dossier(s) ''en vrac'' dont vous" >> /tmp/notice
echo " voulez classer les fichiers. C'est (ce sont) le(s) dossier(s) SOURCE." >> /tmp/notice
echo "- Note : Le dossier CIBLE peut être le même que le dossier SOURCE," >> /tmp/notice
echo " si les fichiers sont tous dans un même dossier. Dans ce cas, on ne" >> /tmp/notice
echo " peut avoir qu'un seul dossier SOURCE, qui est également la CIBLE..." >> /tmp/notice
echo "*** Vous pouvez cliquer sur ''Annuler'' pour mettre fin au script ***" >> /tmp/notice
zenity --text-info --title "Dossier Magique - Mode d'emploi" --height "260" --width "490" --filename "/tmp/notice"
crd=$?; testcrd
fi
# Option "terminal" pour utilisation non graphique
if [ "$en_terminal" = "est_vrai" ]
then
dir_base="${1}"
# Sinon, exécution en mode graphique
else
# On sélectionne d'abord le répertoire cible
dir_base=$(zenity --file-selection --title "Dossier Magique - Choisir répertoire CIBLE" --filename "$dir_base"/ --directory)
crd=$?; testcrd
fi
# Option "graphique" ou par défaut pour utilisation graphique
if [ "$en_terminal" = "est_faux" ]
then
# Protégeons le séparateur standard et initialisons-le à "|"
OLDIFS="${IFS}"
IFS='|'
fi
# Option "terminal" pour utilisation non graphique
if [ "$en_terminal" = "est_vrai" ]
then
# On recherche le(s) paramètre(s) SOURCE(S) éventuel(s)
shift
if [ "${1}" = "" ]
then
# Pas de répertoire SOURCE, alors SOURCE = CIBLE
tab_sce=("$dir_base")
else
# On charge le (la liste des) dossier(s) SOURCE(S)
tab_sce=("${@}")
fi
# Sinon, exécution en mode graphique
else
# On peut sélectionner un ou plusieurs répertoires à trier
# (par défaut, on trie dans le même répertoire cible=source)
tab_sce=($(zenity --file-selection --title "Dossier Magique - Choisir répertoire(s) SOURCE" --filename "$dir_base"/ --directory --multiple))
crd=$?; testcrd
fi
# Définition des répertoires (à adapter si besoin) :
fTXT="${dir_base}/Documents"
fPDF="${dir_base}/Documents"
fAUDIO="${dir_base}/Musique"
fVIDEO="${dir_base}/Vidéos"
fIMG="${dir_base}/Images"
fARCHIVES="${dir_base}/Archives"
fDOCS="${dir_base}/Documents"
fTEX="${dir_base}/Documents"
fMISC="${dir_base}/Divers"
fBIN="${dir_base}/Exécutables"
# Création des répertoires de tri dans le dossier cible
createdirs
for un_sce in "${tab_sce[@]}"
do
# Option "terminal" pour utilisation non graphique
if [ "$en_terminal" = "est_vrai" ]
then
tri "${un_sce}"
else
tri "${un_sce}" | zenity --progress --title "Dossier Magique - Transfert en cours" --auto-close --pulsate --no-cancel
fi
done
# Restaurons le séparateur et le répertoire courant
IFS="${OLDIFS}"
cd "${old_dir_base}"
# Option "graphique" ou par défaut pour utilisation graphique
if [ "$en_terminal" = "est_faux" ]
then
# Restaurons le séparateur standard
IFS="${OLDIFS}"
# Nettoyons les fichiers temporaires générés
rm /tmp/notice /tmp/tri
zenity --info --title "Dossier Magique" --text "Traitement terminé" --timeout "5"
fi
exit 0
Hors ligne
#14 Le 26/05/2020, à 17:18
- Watael
Re : [TUTO Bash] rangement automatique fichiers par extension
vire-moi ces accolades !!! screugneugneu !!!
un nombre se teste avec une Évaluation arithmétique, ou un opérateur de comparaison arithmétique.
utiliser ls pour parcourir la liste qui en sort est une mauvaise pratique.
ce n'est pas à l'utilisateur, ou par défaut, de décider si le script s'exécute dans un terminal ou depuis une autre application graphique (typiquement le gestionnaire de fichiers).
il y a un test pour ça.
l'IFS ne se modifie pas globalement !
pourquoi est-ce qu'on a plusieurs en_terminal == vrai ?
à suivre ...
Connected \o/
Welcome to sHell. · eval is evil.
Hors ligne
#15 Le 26/05/2020, à 18:14
- kholo
Re : [TUTO Bash] rangement automatique fichiers par extension
@watael
oui, j'ai pas encore regardé en profondeur ce script qui est depuis des années dans la doc !
et qui n'est pas de moi !!!
là j'ai juste mis un petit coup de balai histoire qu'il se lise mieux et viré les trucs dont je suis parfaitement certain et au plus rapide...
et justement je le jette un peu en pâture pour avoir l'avis des anciens autant sur le fond que la forme ; son utilité et les améliorations !
mais ok... si personne d'autre ne s'y colle je vais faire ses modifs !
Hors ligne
#16 Le 26/05/2020, à 18:30
- Hizoka
Re : [TUTO Bash] rangement automatique fichiers par extension
Il aime pas les accolades Watael
Continue de les mettre, moi j'aime bien
KDE Neon 64bits
Tous mes softs (MKVExtractorQt, HizoSelect, HizoProgress, Qtesseract, Keneric, Services menus...) sont sur github
Hors ligne
#17 Le 26/05/2020, à 19:19
- Watael
Re : [TUTO Bash] rangement automatique fichiers par extension
c'est pas que j'aime pas les accolades.
Elles surchargent le code sans rien indiqué, et sont donc inutiles. Quand je vois des accolades, j'attends un Substitution de paramètres ("${var//correspondance/remplacment}", par exemple).
j'aime pas le gaspillage.
utiliser des choses en vain, c'est du gaspillage.
Connected \o/
Welcome to sHell. · eval is evil.
Hors ligne
#18 Le 26/05/2020, à 19:27
- kholo
Re : [TUTO Bash] rangement automatique fichiers par extension
... en fait oui j'aime la simplicité de lecture en tant que "non" pro
mais j'ai avancé selon cette première préconisation de Watael de virer le max de guillemets accolades (en effet Watael) et voilà ce que cela donne :
#!/bin/bash
current_ver=1.1.2
# modifications / version 1.1.1
# modifs faites suite post de Watael
# https://forum.ubuntu-fr.org/viewtopic.php?pid=22291873#p22291873
# variables en minuscules modifiées pour être facilement retrouvées
# "function" supprimé des fonctions
# accolade ouvrante des fonctions sur la même ligne que le nom de la fonction
# plus de tabulations remplacées par des espaces
# `fonction` remplacés par $(fonction)
# initialisation des options
en_terminal="est_faux"
en_aide="est_faux"
en_version="est_faux"
en_recursif="est_faux"
# Définition des fonctions du script
# Test du code retour de zenity :
testcrd(){
if [ $crd = -1 ]; then
zenity --error --title "Dossier Magique" --text "Une erreur inattendue s'est produite. Abandon."
exit 2
fi
if [ $crd = 1 ]; then
zenity --info --title "Dossier Magique" --text "Vous avez choisi d'annuler le script. Sortie."
exit 1
fi
return 0
}
# Déplacement d'un fichier et mise à jour du fichier log :
bouge(){
mv "$1" "$2"
heure=$(date +%D-%H:%m)
echo "[$heure] $1 déplacé dans $2" >> $LOG
return 0
}
# Créons les répertoires s'ils n'existent pas :
createdirs(){
mkdir -p "$fTXT"
mkdir -p "$fPDF"
mkdir -p "$fAUDIO"
mkdir -p "$fVIDEO"
mkdir -p "$fIMG"
mkdir -p "$fARCHIVES"
mkdir -p "$fDOCS"
mkdir -p "$fTEX"
mkdir -p "$fMISC"
mkdir -p "$fBIN"
return 0
}
# Trions les fichiers :
tri(){
cd "$1"
# Faut-il gérer la récursivité pour les sources ?
if [[ "$en_recursif" = "est_vrai" && "$dir_base" != "$1" ]]
then
crd=0
while [ $crd = 0 ]
do
ls -d */ 2> /dev/null > /tmp/tri
crd=$?
while read dossier
do
# On remonte tout le dossier d'un niveau
mv -t "./" "$dossier"* 2> /dev/null
# Puis on supprime le dossier vide
rmdir "$dossier"
done < /tmp/tri
done
fi
ls > /tmp/tri
while read fichier
do
# Cas particulier des fichiers à traiter d'après l'extension
type="${fichier##*.}"
case "$type" in
wma) bouge "$fichier" "$fAUDIO";;
*) # Utilisons si possible le type mime :
type=$(file -bi "$fichier")
case "$type" in
*script*) bouge "$fichier" "$fBIN";;
*executable*) bouge "$fichier" "$fBIN";;
*pdf* | *dvi* | *postscript*) bouge "$fichier" "$fPDF";;
*audio* | *ogg*) bouge "$fichier" "$fAUDIO";;
*video* | *flash*) bouge "$fichier" "$fVIDEO";;
*image*) bouge "$fichier" "$fIMG";;
*tar* | *rar* | *zip*) bouge "$fichier" "$fARCHIVES";;
*msword* | *excel* | *powerpoint* | *rtf* | *opendocument*) bouge "$fichier" "$fDOCS";;
*) # Si le type mime ne suffit pas :
type=$(file -b "$fichier")
case "$type" in
*directory*) continue;;
*byte-compiled*) bouge "$fichier" "$fBIN";;
*script*) bouge "$fichier" "$fBIN";;
*LaTeX*) bouge "$fichier" "$fTEX";;
*ASF*) bouge "$fichier" "$fVIDEO";;
*text*) bouge "$fichier" "$fTXT";;
*) # Le type est donc inconnu :
bouge "$fichier" "$fMISC";;
esac
;;
esac
;;
esac
done < /tmp/tri
return 0
}
# Testons d'abord si le script est lancé en mode terminal
while getopts ":agrtv-:" OPT
do
# gestion des options longues avec ou sans argument
[ $OPT = "-" ] && case "${OPTARG%%=*}" in
aide) OPT="a" ;;
graphique) OPT="g" ;;
recursif) OPT="r";;
terminal) OPT="t" ;;
version) OPT="v" ;;
*) echo "Option inconnue" ; exit 1 ;;
esac
# puis gestion des options courtes
case $OPT in
a) en_aide="est_vrai" ;;
g) en_terminal="est_faux" ;;
r) en_recursif="est_vrai";;
t) en_terminal="est_vrai" ;;
v) en_version="est_vrai" ;;
*) echo "Option inconnue" ; exit 1 ;;
esac
done
# Aide
if [ "$en_aide" = "est_vrai" ]
then
echo "Syntaxe 1 : avec 0 ou 1 option et sans paramètre."
echo " $0 Mode graphique."
echo " $0 -g | --graphique Mode graphique."
echo " $0 -a | --aide Affiche l'aide."
echo " $0 -v | --version Affiche la version."
echo " $0 -r | --recursif Gére la récursivité."
echo "Syntaxe 2 : en mode terminal avec paramètre(s) obligatoire(s)."
echo " $0 -t | --terminal CIBLE [SOURCE1 ... SOURCEn]"
echo " où CIBLE est le dossier résultant classé"
echo " et SOURCE(s) le(s) dossier(s) vrac à trier."
echo " Si SOURCE est omis, alors CIBLE=SOURCE."
exit 0
fi
# Version
if [ "$en_version" = "est_vrai" ]
then
echo " "
echo "Version $0 : $current_ver"
# head -15 $0 | grep -v bash
exit 0
fi
# Mémorisons le répertoire courant
old_dir_base=$(pwd)
# Initialisons le dossier racine CIBLE
dir_base="$HOME"
# Définissons le fichier de log (aucun par défaut)
LOG="/dev/null"
# Option "terminal" pour utilisation non graphique
if [ "$en_terminal" = "est_vrai" ]
then
# On élimine les options pour charger le(s) paramètre(s)
while [ "${1:0:1}" = "-" ]
do
shift
done
if [ "$1" = "" ]
then
echo "En mode terminal, indiquer obligatoirement le(s) paramètre(s)"
exit 1
fi
# Sinon, exécution en mode graphique
else
# On affiche d'abord une fenêtre d'aide à l'utilisateur
echo "- Vous allez tout d'abord choisir le dossier dans lequel seront créés" > /tmp/notice
echo " les sous-dossiers où classer les fichiers triés. C'est le dossier CIBLE." >> /tmp/notice
echo "- Vous sélectionnerez ensuite le(s) dossier(s) ''en vrac'' dont vous" >> /tmp/notice
echo " voulez classer les fichiers. C'est (ce sont) le(s) dossier(s) SOURCE." >> /tmp/notice
echo "- Note : Le dossier CIBLE peut être le même que le dossier SOURCE," >> /tmp/notice
echo " si les fichiers sont tous dans un même dossier. Dans ce cas, on ne" >> /tmp/notice
echo " peut avoir qu'un seul dossier SOURCE, qui est également la CIBLE..." >> /tmp/notice
echo "*** Vous pouvez cliquer sur ''Annuler'' pour mettre fin au script ***" >> /tmp/notice
zenity --text-info --title "Dossier Magique - Mode d'emploi" --height "260" --width "490" --filename "/tmp/notice"
crd=$?; testcrd
fi
# Option "terminal" pour utilisation non graphique
if [ "$en_terminal" = "est_vrai" ]
then
dir_base="$1"
# Sinon, exécution en mode graphique
else
# On sélectionne d'abord le répertoire cible
dir_base=$(zenity --file-selection --title "Dossier Magique - Choisir répertoire CIBLE" --filename "$dir_base"/ --directory)
crd=$?; testcrd
fi
# Option "graphique" ou par défaut pour utilisation graphique
if [ "$en_terminal" = "est_faux" ]
then
# Protégeons le séparateur standard et initialisons-le à "|"
OLDIFS="${IFS}"
IFS='|'
fi
# Option "terminal" pour utilisation non graphique
if [ "$en_terminal" = "est_vrai" ]
then
# On recherche le(s) paramètre(s) SOURCE(S) éventuel(s)
shift
if [ "$1" = "" ]
then
# Pas de répertoire SOURCE, alors SOURCE = CIBLE
tab_sce=("$dir_base")
else
# On charge le (la liste des) dossier(s) SOURCE(S)
tab_sce=("$@")
fi
# Sinon, exécution en mode graphique
else
# On peut sélectionner un ou plusieurs répertoires à trier
# (par défaut, on trie dans le même répertoire cible=source)
tab_sce=($(zenity --file-selection --title "Dossier Magique - Choisir répertoire(s) SOURCE" --filename "$dir_base"/ --directory --multiple))
crd=$?; testcrd
fi
# Définition des répertoires (à adapter si besoin) :
fTXT="$dir_base/Documents"
fPDF="$dir_base/Documents"
fAUDIO="$dir_base/Musique"
fVIDEO="$dir_base/Vidéos"
fIMG="$dir_base/Images"
fARCHIVES="$dir_base/Archives"
fDOCS="$dir_base/Documents"
fTEX="$dir_base/Documents"
fMISC="$dir_base/Divers"
fBIN="$dir_base/Exécutables"
# Création des répertoires de tri dans le dossier cible
createdirs
for un_sce in "${tab_sce[@]}"
do
# Option "terminal" pour utilisation non graphique
if [ "$en_terminal" = "est_vrai" ]
then
tri "$un_sce"
else
tri "$un_sce" | zenity --progress --title "Dossier Magique - Transfert en cours" --auto-close --pulsate --no-cancel
fi
done
# Restaurons le séparateur et le répertoire courant
IFS="$OLDIFS"
cd "${old_dir_base}"
# Option "graphique" ou par défaut pour utilisation graphique
if [ "$en_terminal" = "est_faux" ]
then
# Restaurons le séparateur standard
IFS="$OLDIFS"
# Nettoyons les fichiers temporaires générés
rm /tmp/notice /tmp/tri
zenity --info --title "Dossier Magique" --text "Traitement terminé" --timeout "5"
fi
exit 0
NB : encore une fois ce code n'est pas de moi alors je découvre comme vous les raisons de certains choix...
mais je trouve cela assez simple à comprendre
je vois aussi pas mal de lourdeurs que j'utilise comme le exit 0 à la fin, les accolade, ls par exemple (y en a 9 pages sur le forum ! le lien est sur la page de la doc)
Dernière modification par kholo (Le 26/05/2020, à 19:51)
Hors ligne
#19 Le 26/05/2020, à 19:43
- Watael
Re : [TUTO Bash] rangement automatique fichiers par extension
virer le max de guillemets accolades.
les guillemets, au contraire, il vaut mieux en mettre en trop, que pas; comme, par exemple dans [ $OPT = "-" ]
alors qu'ils sont très facultatifs entre double-crochets, et après case.
Connected \o/
Welcome to sHell. · eval is evil.
Hors ligne
#20 Le 26/05/2020, à 20:05
- marcus68
Re : [TUTO Bash] rangement automatique fichiers par extension
en #10
- le dossier est créé même s'il n'y a aucun fichier à déplacer ;
- le fichier est écrasé si un fichier de même nom existe déjà ;
- redéfinir globalement IFS risque de poser problème.
j'avais pas saisi que tu commentait mon exemple. Je vois pas l'intérêt non plus mais on est plus à ça près.
- il suffit de rajouter un test pour que le dossier soit créé que si des fichiers existe
- mv n'ecrases pas par défaut les fichiers rajoute l'option -i à mv pour éviter ce problème
- ça tombe bien, IFS est défini exclusivement dans le script.
Mais merci
Dernière modification par marcus68 (Le 26/05/2020, à 22:42)
Hors ligne
#21 Le 26/05/2020, à 22:23
- beuguissime
Re : [TUTO Bash] rangement automatique fichiers par extension
salut,
- mv n'ecrases pas par défaut les fichiers
bah si
$ touch toto
$ touch titi
$ mv -v titi toto
renamed 'titi' -> 'toto'
Hors ligne
#22 Le 26/05/2020, à 22:41
- marcus68
Re : [TUTO Bash] rangement automatique fichiers par extension
salut,
marcus68 a écrit :- mv n'ecrases pas par défaut les fichiers
bah si
$ touch toto $ touch titi $ mv -v titi toto renamed 'titi' -> 'toto'
ah oui, du coup je vois pas à quoi sert l'option -f.
tu peux rajouter l'option -i alors
Hors ligne
#23 Le 27/05/2020, à 07:00
- bruno
Re : [TUTO Bash] rangement automatique fichiers par extension
Les accolades sont déconseillées en ce moment pour conserver la distance physique.
Sinon pour marcus68, mv -i oblige à répondre à une question. S'il y a 250 fichiers dans ce cas cela va être pénible… (cf man mv pour les options) IFS pourrait très bien être utilisé plus loin dans le script, c'est pourquoi je trouve que c'est une mauvaise habitude de la modifier globalement. Il y a des alternatives, et au pire on peut la déclarer comme locale dans une fonction.
#24 Le 27/05/2020, à 08:08
- marcus68
Re : [TUTO Bash] rangement automatique fichiers par extension
Et donc ? C'est un exemple, on pourrait le développer, mais à quoi bon ?
Pour l'IFS il suffirait de remplacer dans le fichier de base les points virgules par des espaces, et on pourrait se passer de la variable. Et dans mon exemple cela ne gêne en rien.
Bon je suis sur que tu saisses le sujet du post [*]:mad:[/*], moi je ne veux pas développer ce script, il s'agit du script qu'à proposé kholo (voir #1).
J'ai fait l'exemple en 5 minutes pour répondre à "classer des fichiers selon leurs extensions" avec peu de commandes pour interroger la pertinence d'en faire un script de xxx lignes (voir #6). Je n'ai pas évidemment pris en compte toutes les possibilités.
Hors ligne
#25 Le 27/05/2020, à 11:57
- Watael
Re : [TUTO Bash] rangement automatique fichiers par extension
Les accolades sont déconseillées en ce moment pour conserver la distance physique.
mdr !
Connected \o/
Welcome to sHell. · eval is evil.
Hors ligne