Bash: comment supprimer les doublons d'un tableau indicé?

comment supprimer (par une fonction bash ou un script) les doublons du tableau DIRSTACK ?

Je n’ai pas trouvé comment le faire en utilisant que les tableaux.

Ma fonction est encore fausse, en passant par un fichier.temporaire:

# # Supprimer les doublons de la pile des répertoires DIRSTACK (dirs -p, dirs -v, popd, pushd)
popdirs() {
# Afficher la dimension de la pile:
  BIG=$(dirs -p | wc -l) ; echo "BIG=$BIG"
# Afficher le dimension sans les doublons:
  SMALL=$(dirs -p | sort -u | wc -l) ; echo "SMALL=$SMALL"

# 1 Créer la liste réduite:
  dirs -p | sort -u >| DIRS.tmp
# 2 Supprimer la liste actuelle trop longue:
  OLDDIRSTACK="${DIRSTACK[@]}"
  unset DIRSTACK || echo "Erreur 2"
#3 Reconstruire DIRSTACK:
  echo "Reconstruire DIRSTACK:"
  for i in $(cat DIRS.tmp)
  do
    echo "Lecture du fichier DIRS.tmp"
    DIRSTACK=( "{DIRSTACK[@]}" "$i" )
  done
##################
  echo "Fait"
  # contrôle: 
  for i in "${!DIRSTACK[@]}
  do
    echo "Indice=$i, Valeur=${DIRSTACK[$i]}"
  done
  echo "Controlé ?"
#################
#4 vérifier: afficher avec dirs -n
echo  "Afficher la liste triée:"
  dirs -v | sort
echo " Afficher la dimension de la pile:"
  dirs -p | wc -l
  DIRSDIM="$(dirs -p | wc -l)"

# Si le résultat est bon, unset OLDDIRSTACK:
  if [[ "$DIRSDIM" -eq "$SMALL" ]] 
    then
      echo OK
# Tester avant de valider
return 99
    echo "TODO  unset OLDDIRSTACK"
  #Supprimer le fichier DIRS.tmp
    rm DIRS.tmp
    elif [[ "$DIRSDIM" -eq "$BIG" ]] 
    then
      echo "Pile inchangée..."
    elif [[ "$DIRSDIM" -eq 0 ]]  
    then
      echo "Pile vidée"
    else
      echo "Pile de dimension anormale"
  fi  
}

Bonjour,
Tu l’utilises ça dans quel cadre?

J’utilise pushd plutôt que cd. À la longue ça s’allonge avec beaucoup de doublons.

mes aliases les plus utilisés pour cet usage:

Pour choisir dans la liste:
alias pu='dirs -v && read -p ">" && echo $REPLY && let n=$REPLY+0 2>/dev/null && pushd +$REPLY || pushd $REPLY'
Pour faire un «cd» en l’ajoutant dans la pile:
alias pu+='dirs -v ; pushd'

Mais c’est surtout pour entraîner mes neurones avec une fonction bash…

ce que je voulais savoir, c’est à quoi ça sert? quel est le besoin fonctionnnel?

Disposer d’une commande (une fonction dans ~/.bash_function) pour supprimer les doublons dans l’affichage de la pile des répertoires par la commande dirs, afin d’afficher une liste plus courte de répertoires.

sort est ton amis (uniq aussi)

dirs <tes options> |  sort -u

Pas besoin d 'un script :slight_smile:

Pas si simple:

$dirs -v
 0  /home/work/work/ADMIN
 1  /home/work/work/ADMIN/ADMIN_Trixie
 2  /home/work/eric/Ecrire
 3  /usr/local.bkp/local
 4  /usr
 5  /home/work/eric/Ecrire/RH/Planches
 6  /home/work/eric/Ecrire/RH
 7  /home/work/eric/Ecrire

sort fait le tri sur les nombres, pas sur les chemins.

Inverse les colonnes dans ce cas. avec

dirs -V |awk -d '  ' '{ print $1," ",$2 }'

Merci Zargos,
excellente idée
Un problème de syntaxe:
$dirs -v | awk -d ' ' '{ print $1," ",$2 }'
n’affiche rien

oui c’est -F pas -d :smiley:

-d c’est avec cut

et inverser $1 et $2.

$dirs -v | awk -F  '  '  '{ print $2," ",$1 }' | sort -u
/home/work/eric/Domestique_util   12
/home/work/eric/Domestique_util   23
/home/work/eric/Domestique_util   25
/home/work/eric/Domestique_util   50
/home/work/eric/Domestique_util   52

Super je vais suivre cette piste (en début de journée, avant le brouillard cérébral)

Difficulté avec les guillemets et les apostrophes dans la définition de l’alias.
$1 et $2 dans awk sont vides, avec tous les essais entre ", ’ et " et ’ (4 possibilités).
Peut-être qu’une fonction sera plus simple et plus sure.

si tu ne met pas ta commande on ne comprend pas de quoi tu parles

Pardon, je pensais l’avoir donné plus haut.

La commande actuelle qui fonctionne:

alias pu=‹ dirs -v && read -p « > » && echo $REPLY && let n=$REPLY+0 2>/dev/null && pushd +$REPLY || pushd $REPLY ›

Je me rends compte que je mélange tout, et cette commande avec celle que je cherche.

Merci beaucoup,
à plus tard.

Pour awk, $1 désigne le champ 1, $2 le champ 2… et -F indique le séparateur, en l’occurrence l’espace ici. Awk n’est pas du bash, c’est un véritable langage mais ce serait se compliquer la vie que de s’en priver. L’un de ses auteurs est l’un des deux auteurs du langage C. Avec grep, sed, awk, sort et uniq, vous devriez arriver à résoudre la plupart des problèmes du même style.

La documentation d’Awk devrait vous plaire, elle est cependant en anglais et comporte pas moins de 611 pages dans sa version PDF: https://www.gnu.org/software/gawk/manual/. Dès que vous avez un tableau ou il y a des colonnes à inverser, awk doit être un réflexe au moins pour des essais. Il a cependant un défaut car il est lent par rapport à de la programmation en C ou C++ mais cela ne devrait pas poser de problème avec un volume de données relativement faible à traiter.

merci VBreton,
ça ne me dit pas pourquoi, c’est efficace en direct sur la ligne de commande, et pas dans un alias:
$dirs -v | awk -F ' ' '{ print $2," ",$1 }' | sort -u : ne se plaint pas

$alias popdirs="dirs -v | awk -F  '  '  '{ print $2, ,$1 }' | sort -u"
$popdirs 
awk: ligne de commande:1: { print , , }
awk: ligne de commande:1:         ^ syntax error

$alias popdirs="dirs -v | awk -F  '  '  '{ print $2,\"  \ ",$1 }' | sort -u"
$popdirs 
awk: ligne de commande:1: { print ," ", }
awk: ligne de commande:1:         ^ syntax error

(Problème d’affichage du code: les guillemets qui encadrent l’espace, dans le bloc awk, sont échappés ’ ’ ‹ { print $2,\" \ ",$1 } ›, les espaces sont respectés (1 entre les apostrophes de -F, et un entre les guillements échappés de awk

je ne suis pas sur que tu puisse mettre un alias avec un pipe dedans

Les alias sont limités. L’usage de scripts semble plus approprié:

J’ai cru trouver plus simple (dans une fonction):

# 1 effacer  la variable tableau DIRSTACK
unset DIRSTACK
# 2 mettre la sortie  de
#  dirs -p | sort -u
# dans DIRSTACK
DIRSTACK=( $(dirs -p | sort -u) )

Mais (testées directement en ligne de commande) si unset DIRSTACK vide bien la variable DIRSTACK, les commandes pushd, dirs et popd en utilise manifestement une autre, elles ne sont pas affecté par l’effacement de DIRSTACK.

mais ceci est un autre problème.

J’en utilise couramment, par exemple:

psgrep='ps auxw | egrep -i  '

pvdisplay+='echo -e " \e[32m pvdisplay | egrep '\''Physical|Name|PV Size|Allocatable'\''\e[00m";sudo pvdisplay | egrep '\''Physical|Name|PV Size|Allocatable'\'''

df+='df | egrep Uti% && df -Th | egrep '\''^[/]|^[[:blank:]]|tmp$'\'' |egrep '\''[^[:blank:]]*%|VG_tout-.*$'\'''