help-bash
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Help-bash] Putting escaped elements in an array


From: Geir Hauge
Subject: Re: [Help-bash] Putting escaped elements in an array
Date: Mon, 28 Apr 2014 22:07:59 +0200

2014-04-28 19:05 GMT+02:00 Jesper Nygårds <address@hidden>:
> 1. I can't get the 'currentdir=$(readlink -e .; printf x)
> currentdir=${currentdir%?}' line to work. It always leaves $currentdir as
a
> two-line value, i.e. $currentdir is set to the directory plus an empty
> line. Am I missing something?

It removes the x, but forgets to remove the newline readlink -e outputs,
so ${currentdir%$'\nx'} or ${currentdir%??} should do the trick.
However, instead of the highly non-standard ''readlink -e .'', consider
using the builtin pwd command instead. Run ''help pwd'' and see how I
use it below.


> 2. I want to only keep unique values in my array $dirstack, but without
> resorting it. In my original solution, this line works as I would like it
> to:
>
> eval dirstack=( $(printf "%q\n" "address@hidden" | awk '!x[$0]++') )
>
> But I can't get it to work without the eval in there. Without it, quoted
> spaces get lost in successive additions to the array. Is there a way to
> simplify it?

With   array=( $(cmd) )   the result of the command substitution is
subjected to word splitting and pathname expansion. That's why it fails
for spaces and other characters special for word splitting and pathname
expansion. The proper way to populate the array is by using a while read
loop or mapfile (if you don't mind it failing for newlines). See
http://mywiki.wooledge.org/BashFAQ/020


> 3. I only want to keep a limited number of elements in array (say 20).
> Again, I can't get it to work without an eval thrown in:
>
> eval dirstack=( $(printf "%q " "address@hidden:0:20}") )

dirstack=( "address@hidden:0:20}" )


Now, since the only way (assuming you don't write loadable builtins) to
change directory in bash is with the three commands, cd, pushd and popd,
you can limit the case where you do this by overriding cd (and pushd and
popd if you ever use those). I believe this covers all your
requirements:

pushdir() {
    local i dir=$(pwd -P; printf x)
    dir=${dir%$'\nx'}
    for i in "address@hidden"; do
        [[ $dir = "${dirstack[i]}" ]] && unset 'dirstack[i]';
    done
    dirstack=( "$dir" "address@hidden:0:19}" )
}
cd() { builtin cd "$@" && pushdir; }

-- 
Geir Hauge


reply via email to

[Prev in Thread] Current Thread [Next in Thread]