diff --git a/REST/rWosSearchByDoi.sh b/REST/rWosSearchByDoi.sh
new file mode 100755
index 0000000..128b393
--- /dev/null
+++ b/REST/rWosSearchByDoi.sh
@@ -0,0 +1,406 @@
+#!/bin/bash
+
+
+# Initialisation des variables pour les options
+programme=$(basename $0)
+substitut=$(echo $programme | sed 's/./ /g')
+version='0.3.1'
+modif='25/07/2022'
+
+function usage
+{
+echo "Usage : $programme -d (fichier|-) -r (résultats|-) [ -f champs ]* "
+echo " $substitut [ -T taill ] [ -j cookie_jar ] [ -ix ] "
+echo " $programme -h "
+}
+
+function aide
+{
+cat << EOT
+
+Usage
+=====
+ $programme -d (fichier|-) -r (résultats|-) [ -f champs ]*
+ $substitut [ -j cookie_jar ] [ -ix ]
+ $programme -h
+
+Options
+=======
+ -d indique le nom du fichier avec la liste des DOIs à chercher. Si on
+ a un tiret “-” en argument, la liste de DOIs est lue sur l’entrée
+ standard
+ -f limite les champs présents dans les notices téléchargées. Cette
+ option est répétitive (par défaut, tous les champs sont présents)
+ -h affiche cette aide
+ -i ajoute dans la réponse de l’API la liste des identifiants WoS des
+ notices retournées
+ -j indique le nom du fichier qui recevra les cookies (“cookies.txt”
+ -r indique le nom du fichier résultat (pour la sortie standard, utiliser
+ le tiret “-” comme argument de l’option)
+ -T indique le nombre de DOI à chercher à chaque itération (90 par défaut,
+ avec un maximum de 100)
+ -x indique que les notices doivent être en XML au lieu de JSON, le format
+ par défaut
+
+EOT
+
+exit 0
+}
+
+# Déclaration explicite des tableaux “bases” et “champs”
+declare -a champs
+
+format='json'
+
+# Options
+while getopts d:f:hij:r:T:x i
+ do
+ case $i in
+ d) dois=$OPTARG;;
+ f) champs+=$OPTARG;;
+ h) aide;;
+ i) recid=1;;
+ j) cookiejar=$OPTARG;;
+ r) sortie=$OPTARG;;
+ T) taille=$OPTARG;;
+ x) format='xml';;
+ \?) echo >&2
+ usage >&2
+ exit 1;;
+ esac
+ done
+
+# Vérification des options
+if [[ -z $dois || -z $sortie ]]
+then
+ echo "Erreur : option(s) manquante(s)" >&2
+ echo "" >&2
+ usage >&2
+ echo ""
+ exit 2
+fi
+
+if [[ $dois = '-' ]]
+then
+ dois='/dev/fd/0'
+elif [[ ! -f $dois ]]
+then
+ echo "Erreur : fichier \"$dois\" introuvable" >&2
+ exit 3
+fi
+
+if [[ $sortie = '-' ]]
+then
+ sortie='/dev/fd/1'
+fi
+
+if [[ -z $cookiejar ]]
+then
+ cookiejar='cookies.txt'
+fi
+
+# Vérification de la présence des programmes
+# “curl” et “jq”
+for i in curl jq xmllint
+do
+ prog=$(which $i 2> /dev/null)
+ if [[ -z $prog ]]
+ then
+ echo "" >&2
+ echo "Erreur : programme “$i” introuvable. Vérifier \$PATH." >&2
+ echo "" >&2
+ exit 3
+ fi
+done
+
+# Vérification de la variable '$WOS_DELAY'
+if [[ -n $WOS_DELAY && ! $WOS_DELAY =~ ^[1-9][0-9]*$ ]]
+then
+ echo "Erreur : la valeur de la variable \$WOS_DELAY doit être un entier supérieur à 1" >&2
+ exit 2
+fi
+
+# Définition des fichiers de sortie
+out="WosApiOut.$format"
+err='WosApiErr.txt'
+url='https://wos-api.clarivate.com/api/wos'
+
+# Initialisation de la clé
+if [[ -z $key ]]
+then
+ read -t 60 -s -p "clé d‘authentification : " key
+ echo
+ if [ $? -gt 128 ]
+ then
+ echo "" >&2
+ echo "Erreur : temps de réponse (60 s) dépassé " >&2
+ exit 3
+ fi
+fi
+
+# Gestion des autres options
+if [[ ${#champs[@]} -gt 0 ]]
+then
+ optionView='FS'
+ viewField='WOS'
+ for item in ${champs[@]}
+ do
+ while [[ -n $item ]]
+ do
+ deb=${item%%,*}
+ fin=${item#*,}
+ viewField="$viewField+$deb"
+ if [[ $deb = $fin ]]
+ then
+ item=""
+ else
+ item=$fin
+ fi
+ done
+ done
+ extra="\"optionView\": \"FS\", \"viewField\": \"$viewField\""
+else
+ extra="\"optionView\": \"FR\""
+fi
+
+if [[ $recid -gt 0 ]]
+then
+ extra="$extra, \"optionOther\": \"RI+On\""
+fi
+
+function requete
+{
+end=$(( $3 + $2 - 1 ))
+printf " -> %d - %d " $3 $end >&2
+
+cat << EOT > tee search.json
+{
+ "databaseId": "WOS",
+ "lang": "en",
+ "usrQuery": "$1",
+ "count": 100,
+ "firstRecord": 1,
+ $extra
+}
+EOT
+
+if [[ $format = 'json' ]]
+then
+ curl -X POST -d @search.json -b $cookiejar -c $cookiejar -v "$url" \
+ -H "Content-Type: application/json" \
+ -H "X-ApiKey: $key" 2> $err | jq . 2>> $err > $out
+
+ cr=$?
+ echo "Code retour “jq” = $cr" >> $err
+
+ if [[ $cr -gt 0 ]]
+ then
+ echo ""
+ echo "Erreur : la réponse de l‘API est incorrecte [code jq = $cr]" >&2
+ echo ""
+ # nettoie
+ exit 6
+ fi
+
+ # Test de la réponse
+ msg=$(perl -ne 'print "$1" if /"message": "(.+?)"/o' $out)
+ if [[ -n $msg ]]
+ then
+ cod=$(perl -ne 'print "$1" if /"code": "(.+?)"/o' $out)
+ if [[ -n $cod ]]
+ then
+ msg="$cod: $msg"
+ fi
+
+ echo " "
+ echo "Erreur : “$msg” "
+ echo " "
+ # nettoie
+ exit 5
+
+ else
+ qid=$(perl -ne 'print "$1" if /^ +"QueryID": (\d+)/o;' $out)
+ if [[ -n $qid ]]
+ then
+ rec=$(perl -ne 'print "$1" if /^ +"RecordsFound": (\d+)/o;;' $out)
+ top=$(perl -ne 'print "$1" if /^ +"RecordsSearched": (\d+)/o;;' $out)
+
+ if [[ $rec -gt 100 ]]
+ then
+ echo " "
+ echo "Erreur : le nombre de réponses ($rec) est supérieur au maximum autorisé (100)"
+ echo " "
+ # nettoie
+ exit 7
+ fi
+
+ total=$(( $total + $rec ))
+ cat $out >> $sortie
+ fi
+
+ fi
+
+elif [[ $format = 'xml' ]]
+then
+ curl -X POST -d @search.json -b $cookiejar -c $cookiejar -v "$url" \
+ -H "Content-Type: application/json" \
+ -H "Accept: application/xml" \
+ -H "X-ApiKey: $key" 2> $err | xmllint -format - 2>> $err > $out
+
+ cr=$?
+ echo "Code retour “xmllint” = $cr" >> $err
+
+ if [[ $cr -gt 0 ]]
+ then
+ echo ""
+ echo "Erreur : la réponse de l‘API est incorrecte [code xmllint = $cr]" >&2
+ echo ""
+ nettoie
+ exit 6
+ fi
+
+ # Test de la réponse
+ msg=$(perl -ne 'chomp; $l .= $_;}{print "$1" if $l =~ m|(.+?)|;' $out)
+ if [[ -n $msg ]]
+ then
+ code=$(perl -ne 'chomp; $l .= $_;}{print "$1" if $l =~ m|(.+?)
|;' $out)
+ if [[ -n $code ]]
+ then
+ msg="$code: $msg"
+ fi
+
+ echo " "
+ echo "Erreur : “$msg” "
+ echo " "
+ nettoie
+ exit 5
+
+ else
+ qid=$(perl -ne 'print "$1" if m|(\d+)|;' $out)
+ if [[ -n $qid ]]
+ then
+ rec=$(perl -ne 'print "$1" if m|(\d+)|;' $out)
+ top=$(perl -ne 'print "$1" if m|(\d+)|;' $out)
+
+ cat $out >> $sortie
+ fi
+ fi
+
+fi
+
+printf " \r" >&2
+}
+
+# Itéraion sur la liste des DOIs
+max=${taille:-90}
+delai=${WOS_DELAY:-1}
+nb=0
+offset=1
+total=0
+
+# Vérification des variables “$max” et “$delai”
+if [[ $max -lt 1 ]]
+then
+ echo "Erreur : le nombre de notices par itération doit être compris entre 1 et 100" >&2
+ exit 4
+elif [[ $max -gt 100 ]]
+then
+ echo "Erreur : le nombre de notices par itération ne peut dépasser 100" >&2
+ exit 4
+fi
+
+if [[ $delai -lt 1 ]]
+then
+ echo "Erreur : la variable \$WOS_DELAY ne peut pas valoir moins d‘une seconde"
+ exit 4
+fi
+
+SECONDS=0
+
+while read x
+do
+ nb=$(( $nb + 1 ))
+
+ if [[ $nb -eq 1 ]]
+ then
+ liste="\\\"$x\\\""
+ else
+ liste="$liste OR \\\"$x\\\""
+ fi
+
+ if [[ $nb -eq $max ]]
+ then
+ requete "DO=($liste)" "$nb" "$offset"
+ offset=$(( $offset + $nb ))
+ liste=""
+ nb=0
+
+ while [[ $SECONDS -lt $delai ]]
+ do
+ sleep 0.5
+ done
+ SECONDS=0
+
+ fi
+done < $dois
+
+if [[ $nb -gt 0 ]]
+then
+ requete "DO=($liste)" "$nb" "$offset"
+fi
+
+nb=$(( $offset + $nb - 1 ))
+
+if [[ $format = 'json' ]]
+then
+ perl -ne 'if (not $m) {
+ if (/^( +)\{/o) {
+ $m = $1;
+ if ($ok) {
+ print ",";
+ $ok = 0;
+ }
+ print;
+ }
+ }
+ else {
+ if (/^$m/o) {
+ print;
+ $n ++;
+ }
+ else {
+ $ok ++ if $n;
+ $m = "" if /^\{/o;
+ }
+ }' $sortie |
+ (echo '{"Records": {"records": {"REC": ['; cat; echo ']}}}') |
+ jq . > tmpWos$$.json
+
+ mv tmpWos$$.json $sortie
+# offset=$(perl -ne '$nb ++ if /"UID": /o;}{print $nb;' $sortie)
+else
+ perl -ne 'foreach $rec (m|()|go) {
+ print "$rec\n";
+ }' $sortie |
+ (echo ''; cat; echo '') |
+ xmllint -format - > tmpWos$$.xml
+
+ mv tmpWos$$.xml $sortie
+# offset=$(perl -ne 'foreach $r (m|(&2
+echo " " >&2
+echo "Nombre de DOIs cherchés : $nb" >&2
+(echo "Nombre de notices trouvées : $total / $top notices"
+ echo "Forfait restant : $amt" ) |
+ perl -pe '1 while(s/(\d)(\d\d\d)\b/$1 $2/o);' >&2
+
+
+exit 0
+
+
+
+