Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

Re: more fun with parameter expansion



On Jun 16,  2:00pm, Bart Schaefer wrote:
> Subject: Re: more fun with parameter expansion
> 
> for f in **/*(DNon); do
>   mv -v $f ${${(M)f%/*}:+${${f%/*}:l:gs/ /_/}}${${${(M)f%/*}:-$f}:l:gs/ /_/}
> done
> 
> The `(on)' (order by name) is probably unnecessary, and won't work in 3.0.x
> (though everything else should).

Of course I completely forgot that the whole reason I split the thing into
head and tail was because this needs to work in REVERSE name order.  Sigh.

The correct solution is

for f in **/*(DNOn^M); do
  mv -v $i ${${(M)i%/*}:+${i%/*}}${${${(M)i%/*}:-$i}:l:gs/ /_/}
done

(note one fewer :l:gs and turn *off* markdirs) which *won't* work in 3.0.x
because of no (On) glob flag.

> Writing that one-liner out a bit longer might make this more readable:
> 
>   t=${(M)f%/*}     # The tail of the path, including leading slash
>   h=${t:+${f%/*}}  # The head of the path if the tail is non-empty
>   t=${t:-$f}       # The tail is the path when the tail is empty
> 
>   h=$h:l           # Downcase the head, same as ${(L)h}
>   h=$h:gs/ /_/

This was my error; don't modify the head, instead wait for it to become
the tail (that's why the reverse ordering) and then modify it.

>   t=$t:l           # Downcase the tail
>   t=$h:gs/ /_/

And I forgot that braces are needed because of the space:

    t=${t:gs/ /_/}

>   mv $f $h$t
> 
> The last five steps could be written as
> 
>   mv $f ${${:-$h$t}:l:gs/ /_/}

Rather:

    mv $f $h${t:l:gs/ /_/}

which isn't nearly as mysterious.  Oh well.



Messages sorted by: Reverse Date, Date, Thread, Author