- on all Unix-like operating systems (such as Linux and Mac OS X), the directory structure has a Unix syntax, with separate file paths separated by a colon (
:
) - on Windows, the directory structure has a Windows syntax, and each file path must be separated by a semicolon (
;
) - when the Classpath is defined in manifest files, where each file path must be separated by a space (
- Nom d'un fichier depuis son chemin complet
basename /che/min/fic
=>fic
- Chemin du dossier d'un fichier depuis son chemin complet
dirname /che/min/fic
=>/che/min
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
---|---|---|---|---|---|---|---|
- |
x |
w |
wx |
r |
rx |
rw |
rwx |
chmod +x fic
ouchmod u+x fic
ouchmod g+x fic
ouchmod o+x fic
# Nom du shell
PROG_NAME=$(basename "$0")
# Nom de la machine
HOST_NAME=$(hostname)
# Version courte
SHORT_HOST_NAME="$(hostname --short)"
# Informations du système (OS, host)
SYSTEM_INFO=$(uname --all)
# Utilisateur exécutant le script
USER=$(id -u -n)
# Version Java
JAVA_VERSION=$(java -version 2>&1 | grep 'java version' | tr -d \")
echo " HOST_NAME=${HOST_NAME}"
echo " SCRIPT=$0"
echo " EXECUTE PAR=${USER}"
echo " ENVIRONNEMENT=${SYSTEM_INFO}"
echo " VERSION CENTOS=$(cat /etc/centos-release)"
echo " VERSION REDHAT=$(cat /etc/redhat-release)"
read -p "Message" nomvariable
echo "Saisie=${nomvariable}"
Date au format AAAAMMJJ :
echo `date '+%C%y%m%d'`
Date au format AAAAMMJJ HH:mm:ss :
logdate=`date '+%C%y%m%d'-%H:%M:%S`
Calcul sur une date :
date_moins_7_jour=`date '+%C%y%m%d' -d "$ma_date-7 days"`
# If variable not set or null, use default.
LIQUIBASE_COMMAND=${1:-status}
# If variable not set or null, set it to default.
LIQUIBASE_COMMAND=${1:=status}
$?
représente le code retour de la commande précédente$$
représente le PID du shell qui interprète le script$!
représente le PID d'une commande exécutée en arrière plan$-
représente ?$_
représente ?
$#
nombre de paramètres reçus$0
nom du script$*
tous les paramètres (sous forme d'une seule chaîne)$@
tous les paramètres (sous forme d'un tableau)$1
1er paramètre$2
2eme paramètre
$*
et $@
lorsqu'elles ne sont pas entourées par des guillemets sont équivalentes : $@
has each parameter as a separate quoted string, whereas $*
has all parameters as a single string.
- Majuscules
${var^^}
- Minuscules
${var,,}
extension="${filename##*.}"
extension du fichierfilename="${filename%.*}"
nom du fichier sans l'extension
~% FILE="example.tar.gz"
~% echo "${FILE%%.*}"
example
~% echo "${FILE%.*}"
example.tar
~% echo "${FILE#*.}"
tar.gz
~% echo "${FILE##*.}"
gz
Avec elif et else :
if [ condition ]; then
echo "Le premier test a été vérifié"
elif [ autre_condition ]; then
echo "Le second test a été vérifié"
elif [ encore_autre_condition ]; then
echo "Le troisième test a été vérifié"
else
echo "Aucun des tests précédents n'a été vérifié"
fi
Avec et (&&
) / ou (||
) :
if [ condition1 ] && [ condition2 ]
if [[ ${CONTEXT_ROOT} == "" || ${LIV_DIR} == "" || ${WAR_URL} == "" ]]; then
echo "[INSTALL] ECHEC : Attendu 3 arguments <artifactId> <livraisonDir> <warUrl>"
exit 10
fi
if [[ ($1 != "--help") && (${CONTEXT_ROOT} == "" || ${LIV_DIR} == "" || ${WAR_URL} == "") ]]; then
echo "[INSTALL] ECHEC : Attendu 3 arguments <artifactId> <livraisonDir> <warUrl>"
exit 10
fi
Avec et (-a
) / ou (-o
) :
if [ $foo -ge 3 -a $foo -lt 10 ]; then
echo "foo >= 3 && foo < 10"
fi
ℹ️ En rajoutant un !
devant :
if [ ! condition ]; then
echo "condition non vérifiée"
fi
ℹ️ enhanced version of the single-bracket syntax
- an asterisk (“*”) will expand to literally anything
- word splitting is prevented, you could omit placing quotes around string variables
- not expanding filenames
- combining expressions (
[[ cond1 && cond2 || cond3 ]]
) - allows regex pattern matching using the “=~”
ℹ️ for arithmetic (number-based) conditions.
if (( $num <= 5 )); then
echo "num <= 5"
fi
Condition | Mnémonique | Signification |
---|---|---|
-e $nomfichier |
exists | Vérifie si le fichier existe. |
-a $nomfichier |
available | Vérifie si le fichier existe (obsolète). |
-b $nomfichier |
bloc | Vérifie si le fichier périphérique de type bloc existe. |
-c $nomfichier |
char | Vérifie si le fichier périphérique de type caractères existe. |
-p $nomfichier |
pipe | Vérifie si le fichier tube existe. |
-f $nomfichier |
file | Vérifie si le fichier est un fichier. Un vrai fichier cette fois, pas un dossier. |
-d $nomfichier |
directory | Vérifie si le fichier est un répertoire. N'oubliez pas que sous Linux, tout est considéré comme un fichier, même un répertoire ! |
-r $nomfichier |
readable | Vérifie si le fichier est lisible (r). |
-w $nomfichier |
writable | Vérifie si le fichier est modifiable (w). |
-x $nomfichier |
executable | Vérifie si le fichier est exécutable (x). |
-u $nomfichier |
user | Vérifie si l'utilisateur dispose de la permission set-user-id (suid) sur ce fichier. |
-g $nomfichier |
group | Vérifie si le groupe est positionné sur le fichier. |
-k $nomfichier |
stiKy | Vérifie si le stiky-bit est positionné sur le fichier. |
-L $nomfichier |
Link | Vérifie si le fichier est un lien symbolique (raccourci). |
-h $nomfichier |
? | Vérifie si le fichier est un lien symbolique (raccourci). |
-s $nomfichier |
size | Vérifie si le fichier n'est pas vide (taille > 0). |
-S $nomfichier |
Socket | Vérifie si le fichier existe et est un socket. |
-O $nomfichier |
Owner | Vérifie si le fichier existe et si on est le propriétaire. |
-N $nomfichier |
? | Vérifie si le fichier a été modifié depuis sa dernière lecture. |
$fichier1 -nt $fichier2 |
newerthan | Vérifie si fichier1 est plus récent que fichier2 . |
$fichier1 -ot $fichier2 |
olderthan | Vérifie si fichier1 est plus vieux que fichier2 . |
$fichier1 -ef $fichier2 |
? | Vérifie si fichier1 et fichier2 sont des liens physiques pointant vers le même fichier. |
💡 https://abs.traduc.org/abs-fr/ch07s02.html
# Test si un dossier n'est pas présent
if [ ! -d "${INPUT_ROOT_DIR}" ]; then
echo "Dossier racine input ${INPUT_ROOT_DIR} introuvable"
exit 1
fi
# Test si un fichier n'est pas présent
if [ ! -f "${INPUT_FILE}" ]; then
echo "Fichier input ${INPUT_FILE} introuvable"
exit 1
fi
if [ $? -ne 0 ]; then
echo "différent de 0"
fi
if [ $? -eq 0 ]; then
echo "égal à 0"
fi
Egalité :
if [ ${count} = 0 ]; then
echo "count vaut zero"
fi
if [ ${var1} -eq ${var2} ]; then
echo "var1 == var2"
fi
Différence :
if [ ${var1} -ne ${var2} ]; then
echo "var1 != var2"
fi
Inférieur :
if [ ${var1} -lt ${var2} ]; then
echo "var1 < var2"
fi
if [ ${var1} -le ${var2} ]; then
echo "var1 <= var2"
fi
Supérieur :
if [ ${var1} -gt ${var2} ]; then
echo "var1 > var2"
fi
if [ ${var1} -ge ${var2} ]; then
echo "var1 >= var2"
fi
if [ -z $variable ]; then
echo "Variable vide"
fi
if [ -n $variable ]; then
echo "Variable non vide"
fi
if [ $variable = "valeur" ]; then
echo "Variable vaut valeur"
fi
# mais aussi avec ==
if [[ $variable == "valeur" ]]; then
echo "Variable vaut valeur"
fi
if [ $variable != "valeur" ]; then
echo "Variable différent valeur"
fi
if [ ${#variable} != 2 ]; then
echo "Variable n'est pas de longeuur 2"
fi
# double [[ ]] obligatoire ici (et le * en dehors des guillemets!)
if [[ $variable == "valeur"* ]]; then
echo "Variable commence par valeur"
fi
🔗 https://www.admin-linux.fr/controle-des-ressources-systemes-ulimit/ | https://buzut.developpez.com/tutoriels/ulimit/
usage: ulimit [-SHacdefilmnpqrstuvx] [limit]
- S : limite soft : si l'utilisateur souhaite repousser cette limite, il devra définir une nouvelle limite soft avec ulimit
- H : limite hard : limite maximale
Option | Description |
---|---|
-a | Afficher les limitations |
-c | Limiter la création de fichier core dump |
-u | Restreindre le nombre de processus simultanés |
-t | Limiter le temps CPU |
-r | Limiter la priorité des processus lancés |
-n | Limiter le nombre de fichiers ouverts |
-f | Limiter la taille des fichiers écrits |
-p | Limiter le nombre de pipes |
driver_filename="${URL_JAR_JDBC##*/}"
Stocker la réponse dans une variable :
response=$(curl --request POST ${CURL_PARAMS} ${URL_WS_SOLARIS}/$1/$2)
Récupération du statut HTTP :
response=$(curl -sw '\n%{http_code}' ...) # -sw pour rajouter une ligne à la fin contenant le statut HTTP
http_status=$(printf "$response" | tail --lines=1) # tail pour récupérer la valeur
if [ $http_status -eq 200 ]; then
# OK
else
# KO
fi
--fail
, voir ci-après)
Télécharger un fichier :
curl -L ${FLE_URL} -o ${OUTPUT_DIR}/file
# --fail pour verifier que ca se passe bien
if ! curl --fail --location "${FLE_URL}" --output "${OUTPUT_DIR}/file"
then
exit 1
fi
ou pour conserver le nom d'origine :
curl --location https://storage.googleapis.com/shellcheck/shellcheck-stable.linux.x86_64.tar.xz --remote-name
Poster des données :
curl --header "content-type: application/json" --data "{\"param\": \"value\"}" http://localhost:8080
Référencer un fichier :
curl --header "content-type: text/xml" --data @folder/data.xml http://localhost:8080
Multipart Form :
curl -F "livraison={\"codeSa\":\"MONAPP\",\"packageAuto\":false,\"versionSa\":\"VERSION_SA\",\"patch\": \"PATCH\",\"codeProjet\":\"\",\"tagSources\":\"TAG_NAME\",\"codeFiliere\":\"OPN\"};type=application/json" -F "file=@%WORKSPACE_DEV%\app\app-livraison\target\livraison.zip" --user "%BUILD_USER_ID%:%PASSWORD%" https://app.entreprise/services/livraison?deliver=%LIVRER%
Common arguments :
-s, --silent
: don't output anything-v, --verbose
: mode verbeux-V, --version
: affichage de la version--noproxy app.entreprise.fr
: turn-off proxy for this URL--insecure
: turn-off SSL certificate verification--user "USER_ID:PASSWORD"
-w, --write-out
: output after completion
wget -nv -P ${OUTPUT_DIR} ${FLE_URL}
chown -R vagrant:vagrant $FOLDER
chown vagrant:vagrant $FILE
source is a bash specific shell built-in command that executes the content of the file passed as argument, in the current shell. It has a synonym in . (period).
- Il vaut mieux utiliser
.
qui est le standard - Le script va s'exécuter avec le même contexte que le script qui le lance (variables, fonctions, ...)
- Un
exit
dans le script appelé va entraîner l'arrêt du script appelant
ℹ️ Interprétation des backslash : echo -e "\n"
ℹ️ Afficher l'aide : help echo
ℹ️ Ne pas faire de saut de ligne à la fin : echo -n "str"
Recherche textuelle dans des fichiers. Exemple : grep -rnw '/path/to/somewhere/' -e 'pattern'
grep -rnw '/path/to/somewhere/' -e 'pattern'
-q
or--quiet
suppress all normal output,-r
or-R
is recursive,-n
is line number, and-w
stands for match the whole word.-l
(lower-case L) can be added to just give the file name of matching files.-v
affiche les lignes ne contenant pas la chaîne-c
compte le nombre de lignes contenant la chaîne-x
ligne correspondant exactement à la chaîne
Along with these, --exclude
, --include
, --exclude-dir
flags could be used for efficient searching:
- This will only search through those files which have .c or .h extensions:
grep --include=\*.{c,h} -rnw '/path/to/somewhere/' -e "pattern"
- This will exclude searching all the files ending with
.o
extension:grep --exclude=*.o -rnw '/path/to/somewhere/' -e "pattern"
- For directories it's possible to exclude a particular directory(ies) through
--exclude-dir
parameter. For example, this will exclude the dirs dir1/, dir2/ and all of them matching *.dst/:grep --exclude-dir={dir1,dir2,*.dst} -rnw '/path/to/somewhere/' -e "pattern"
Petite fonction utile :
search() {
grep -rnw '.' -e "$1"
}
- 💡 Recherche des lignes ne contant pas un motif :
grep -v "mon motif" monfichier.txt
- 💡 Recherche des fichiers ne contant pas un motif :
grep -L "mon motif" *.txt
echo $data | tail --lines=<n>
avec<n>
le nombre de lignes en partant de la finecho $data | head --lines=<n>
avec<n>
le nombre de lignes en partant du début
ou --bytes=<n>
avec <n>
le nombre d'octets
ℹ️ head : with the leading '-', print all but the last <n>
bytes of each file
- Compter les fichiers "sh" d'une arborescence :
find . -type f -name "*.sh" -ls | wc -l
ℹ️ Syntaxe : wc [OPTION]... [FILE]...
-c, --bytes print the byte counts
-m, --chars print the character counts
-l, --lines print the newline counts
--files0-from=F read input from the files specified by
NUL-terminated names in file F;
If F is - then read names from standard input
-L, --max-line-length print the length of the longest line
-w, --words print the word counts
ℹ️ Syntaxe : cut -d<sep> -f<nb>
cut -d: -f1 /etc/passwd
java -version 2>&1 | grep 'java version' | tr -d \" | cut -d' ' -f3
TR permet de traduire (remplacer) ou supprimer des caractères.
ℹ️ Syntaxe : tr -options motif1 motif2
# suppression des guillemets
java -version 2>&1 | tr -d \"
# suppression des sauts de ligne
commande1 | tr -d '\n' | commande2
# Remplacement de caractères
echo cuicui | tr ui ou
# Convertir toutes les MAJUSCULES en minuscules
echo COUCOU | tr [:upper:] [:lower:]
GITLAB_USER_LOGIN=GS2250
token_GS2250=666
echo "user -> " ${GITLAB_USER_LOGIN}
token=$(eval "echo \${token_${GITLAB_USER_LOGIN}}")
echo "TOKEN=${token}"
- The -i option causes the file to be edited "in place"
sed -i~
optional argument to create a backup file
# Token sous forme {{token}}
sed -i "s/{{montoken}}/${mavariable}/g" $FILE
# Token sous forme ${token}
sed -i "/${montoken}=/ s/=.*/=${mavariable}/" $FILE
# Regexp
sed -i "s/Exec=.*/Exec=\/usr\/share\/code\/code --unity-launch \/home\/vagrant\/git\/DOMINOS %F/g" /home/vagrant/Desktop/code.desktop
# Suppression des lignes vide d'un fichier
sed -i "/^$/d" ${file}
🔗 http://www.theunixschool.com/2014/08/sed-examples-remove-delete-chars-from-line-file.html
The best way to deal with paths in sed is to use a character other than / as the regexp delimeter --any will do, i.e.
sed s,a,b,
# is just the same as
sed s/a/b/
Then you don't have to escape the slashes in the search/replace patterns.
sed -e "s#@@DLVR_COMPOSANT@@#${Composant}#g" \
-e "s#@@DLVR_TIMESTAMP@@#${DateReq}#g" \
-e "s#@@DLVR_PACKAGE_AUTHORNAME@@#${Auteur}#g" \
-e "s#@@DLVR_PACKAGE_CREATIONDATE@@#${DateReq}#g" \
-e "s#@@DLVR_PRODUCT_NAME@@#${IN_CODE_SA}#g" \
-e "s#@@DLVR_PACKAGE_NAME@@#${Composant}.${DateReq}.tar.gz#g" \
-e "s#@@APPFOLDEROWNERNAME@@#${UserPwc}#g" \
-e "s#@@APPFOLDERGROUPNAME@@#${GrpPwc}#g" \
-e "s#@@DLVR_APP_NAME@@#${IN_TRIGRAMME}#g" \
${BATCH_DIR}/LIV_Install_Model.txt >${InstallScript}
🔗 awk
# TODO
output=$(df -h ${HANGAR_DIR})
usedspace=`echo "${output}" | tail -n +3 | awk '{ print $4 }' | cut -d '%' -f1`
# Taille d'un dossier sans afficher tous les sous-dossiers (-s)
du -h -s /sonatype-work/storage/g2s-binary/
# TODO
- 🔗 https://www.quennec.fr/trucs-astuces/syst%C3%A8mes/gnulinux/programmation-shell-sous-gnulinux/param%C3%A9trer-son-environnement-de-travail/les-options-du-shell
- 🔗 https://www.gnu.org/software/bash/manual/html_node/The-Set-Builtin.html
Tableau d'équivalence :
set -? | set -o ? |
---|---|
a | allexport |
b | notify |
e | errexit |
f | noglob |
h | hashall |
🚫 | history |
🚫 | ignoreeof |
k | keyword |
m | monitor |
n | noexec |
p | privileged |
🚫 | pipefail |
🚫 | posix |
t | onecmd |
u | nounset |
v | verbose |
x | xtrace |
B | braceexpand |
C | noclobber |
E | errtrace |
H | histexpand |
P | physical |
T | functrace |
🚫 | emacs |
🚫 | vi |
Détail sur certaines options :
Version courte | Version longue | Description |
---|---|---|
set -u |
set -o nounset |
Ne pas autoriser les variables non définies |
set -v |
set -o verbose |
Affiche la ligne avant de l'exécuter |
set -x |
set -o xtrace |
Affiche l'exécution des commandes après traitement des caractères spéciaux (ex: $var) |
set -n |
set -o noexec |
Permet la détection des erreurs de syntaxe via la lecture des commandes mais sans les exécuter |
set -e |
set -o errexit |
Force l'arrêt du script en cas d'erreur |
🚫 | set -o ignoreeof |
L'arrêt du script n'est plus possible via CTRL+D |
set -f |
set -o noglob |
Les caractères jokers (*?[] ) ne sont pas interprétés |
set -C |
set -o noclobber |
Avertissement quand une redirection va écraser un fichier existant |
🔗 Syntaxe getopts
https://wiki.bash-hackers.org/howto/getopts_tutorial
🔗 Syntaxe GNU-Style TODO
#!/bin/sh
# Index de parcours des tableaux de noms et d'ID
GIT_REPO_INDEX="0 1 2"
# Noms des depots
GIT_REPO_NAMES[0]=REPO1
GIT_REPO_NAMES[1]=REPO2
GIT_REPO_NAMES[2]=REPO3
# Identifiants des depots pour l'API
GIT_REPO_IDS[0]=396
GIT_REPO_IDS[1]=433
GIT_REPO_IDS[2]=397
echo "GIT_REPO_INDEX=${GIT_REPO_INDEX[*]}"
echo "GIT_REPO_NAMES=${GIT_REPO_NAMES[*]}"
echo "GIT_REPO_IDS=${GIT_REPO_IDS[*]}"
for INDEX in ${GIT_REPO_INDEX}; do
echo "${INDEX} | NAME ${GIT_REPO_NAMES[${INDEX}]} | ID ${GIT_REPO_IDS[${INDEX}]}"
done