How to drop an argument (from the list of arguments) in a shell script?

Multi tool use
Multi tool use

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP











up vote
0
down vote

favorite












I have the following (MWE) shell script foo:



#!/bin/bash
ARGS=("$@") # all arguments
## => if it exists, we need to drop the argument "-D" here
ls -l $ARGS[@] | sort -fk8


If foo is called with argument -D (the position in the list of arguments is unknown), how can I remove -D from the list of arguments? I found out that unset ARGS[$#ARGS[@]-1] can drop the last argument, for example, but I'm not sure in which order the arguments are passed (so I first need to know at which place the argument is and then remove it in case it is provided).







share|improve this question




















  • Why do you need it?
    – choroba
    Nov 11 '17 at 11:52










  • That's why: emacs.stackexchange.com/questions/36798/… and because I'm simply interested in how this can be done in shell scripts.
    – Marius Hofert
    Nov 11 '17 at 11:56















up vote
0
down vote

favorite












I have the following (MWE) shell script foo:



#!/bin/bash
ARGS=("$@") # all arguments
## => if it exists, we need to drop the argument "-D" here
ls -l $ARGS[@] | sort -fk8


If foo is called with argument -D (the position in the list of arguments is unknown), how can I remove -D from the list of arguments? I found out that unset ARGS[$#ARGS[@]-1] can drop the last argument, for example, but I'm not sure in which order the arguments are passed (so I first need to know at which place the argument is and then remove it in case it is provided).







share|improve this question




















  • Why do you need it?
    – choroba
    Nov 11 '17 at 11:52










  • That's why: emacs.stackexchange.com/questions/36798/… and because I'm simply interested in how this can be done in shell scripts.
    – Marius Hofert
    Nov 11 '17 at 11:56













up vote
0
down vote

favorite









up vote
0
down vote

favorite











I have the following (MWE) shell script foo:



#!/bin/bash
ARGS=("$@") # all arguments
## => if it exists, we need to drop the argument "-D" here
ls -l $ARGS[@] | sort -fk8


If foo is called with argument -D (the position in the list of arguments is unknown), how can I remove -D from the list of arguments? I found out that unset ARGS[$#ARGS[@]-1] can drop the last argument, for example, but I'm not sure in which order the arguments are passed (so I first need to know at which place the argument is and then remove it in case it is provided).







share|improve this question












I have the following (MWE) shell script foo:



#!/bin/bash
ARGS=("$@") # all arguments
## => if it exists, we need to drop the argument "-D" here
ls -l $ARGS[@] | sort -fk8


If foo is called with argument -D (the position in the list of arguments is unknown), how can I remove -D from the list of arguments? I found out that unset ARGS[$#ARGS[@]-1] can drop the last argument, for example, but I'm not sure in which order the arguments are passed (so I first need to know at which place the argument is and then remove it in case it is provided).









share|improve this question











share|improve this question




share|improve this question










asked Nov 11 '17 at 11:39









Marius Hofert

2441411




2441411











  • Why do you need it?
    – choroba
    Nov 11 '17 at 11:52










  • That's why: emacs.stackexchange.com/questions/36798/… and because I'm simply interested in how this can be done in shell scripts.
    – Marius Hofert
    Nov 11 '17 at 11:56

















  • Why do you need it?
    – choroba
    Nov 11 '17 at 11:52










  • That's why: emacs.stackexchange.com/questions/36798/… and because I'm simply interested in how this can be done in shell scripts.
    – Marius Hofert
    Nov 11 '17 at 11:56
















Why do you need it?
– choroba
Nov 11 '17 at 11:52




Why do you need it?
– choroba
Nov 11 '17 at 11:52












That's why: emacs.stackexchange.com/questions/36798/… and because I'm simply interested in how this can be done in shell scripts.
– Marius Hofert
Nov 11 '17 at 11:56





That's why: emacs.stackexchange.com/questions/36798/… and because I'm simply interested in how this can be done in shell scripts.
– Marius Hofert
Nov 11 '17 at 11:56











2 Answers
2






active

oldest

votes

















up vote
3
down vote



accepted










The no-frills approach is to simply loop over the positional parameters, collecting all but -D into an array, and then use set -- to update the params:



for param; do 
[[ ! $param == '-D' ]] && newparams+=("$param")
done
set -- "$newparams[@]" # overwrites the original positional params





share|improve this answer






















  • In bash, you can even do newparams+=("$param").
    – choroba
    Nov 11 '17 at 12:13










  • Oh, yeah. I always forget if Bash has that or not. Thanks for the reminder.
    – B Layer
    Nov 11 '17 at 12:15











  • Downvoted because...why?
    – B Layer
    Nov 25 '17 at 20:53


















up vote
4
down vote













With zsh, use the $array:#pattern parameter expansion operator:



$ set foo -D -D bar '' $'anb'
$ printf '<%s>n' "$@:#-D"
<foo>
<bar>
<>
<a
b>


POSIXly:



for i do
[ "$i" = -D ] || set -- "$@" "$i"
shift
done
printf '<%s>n' "$@"


BTW, you forgot the quotes, -- and -d:



ls -ld -- "$@"


If you want to sort by modification time, you can just use the -t option, here with -r (reverse) for oldest first:



ls -lrtd -- "$@"


Beware that if $ARGS is an empty array, it will list .. So you can do:



[ "$@" -eq 0 ] || ls -lrtd -- "$@"


To sort reliably based on the hour of the day irrespective of date, with zsh and a ls implementation that supports -U for not sorting:



zmodload zsh/stat # best in ~/.zshrc
bytime() zstat -LA REPLY -F%T +mtime -- $REPLY
ls --full-time -ldU -- .(e'reply=("$@")'o+bytime)


With limited shells like bash, it's very hard to sort files based on arbitrary metadata like that. Again, if you've got access to recent GNU tools, it's slightly easier:



[ "$#" -gt 0 ] && (
export LC_ALL=C
printf '%s' "$@" |
sed -z 's|^-$|./-|' |
xargs -r0 stat --printf '%yt%n' -- |
sort -zk2,2 |
cut -zf 2-
) | xargs -r0 ls -lUd --


Portably (but still using the non-standard ls -U here), it's generally easier to resort to perl, like:



perl -MPOSIX -e '
exec qwls -ldU --,
map $_->[1]
sort $a->[0] cmp $b->[0]
map [strftime("%T", localtime((lstat$_)[9])), $_]
@ARGV' -- "$@"





share|improve this answer






















    Your Answer







    StackExchange.ready(function()
    var channelOptions =
    tags: "".split(" "),
    id: "106"
    ;
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function()
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled)
    StackExchange.using("snippets", function()
    createEditor();
    );

    else
    createEditor();

    );

    function createEditor()
    StackExchange.prepareEditor(
    heartbeatType: 'answer',
    convertImagesToLinks: false,
    noModals: false,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: null,
    bindNavPrevention: true,
    postfix: "",
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    );



    );













     

    draft saved


    draft discarded


















    StackExchange.ready(
    function ()
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f403890%2fhow-to-drop-an-argument-from-the-list-of-arguments-in-a-shell-script%23new-answer', 'question_page');

    );

    Post as a guest






























    2 Answers
    2






    active

    oldest

    votes








    2 Answers
    2






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes








    up vote
    3
    down vote



    accepted










    The no-frills approach is to simply loop over the positional parameters, collecting all but -D into an array, and then use set -- to update the params:



    for param; do 
    [[ ! $param == '-D' ]] && newparams+=("$param")
    done
    set -- "$newparams[@]" # overwrites the original positional params





    share|improve this answer






















    • In bash, you can even do newparams+=("$param").
      – choroba
      Nov 11 '17 at 12:13










    • Oh, yeah. I always forget if Bash has that or not. Thanks for the reminder.
      – B Layer
      Nov 11 '17 at 12:15











    • Downvoted because...why?
      – B Layer
      Nov 25 '17 at 20:53















    up vote
    3
    down vote



    accepted










    The no-frills approach is to simply loop over the positional parameters, collecting all but -D into an array, and then use set -- to update the params:



    for param; do 
    [[ ! $param == '-D' ]] && newparams+=("$param")
    done
    set -- "$newparams[@]" # overwrites the original positional params





    share|improve this answer






















    • In bash, you can even do newparams+=("$param").
      – choroba
      Nov 11 '17 at 12:13










    • Oh, yeah. I always forget if Bash has that or not. Thanks for the reminder.
      – B Layer
      Nov 11 '17 at 12:15











    • Downvoted because...why?
      – B Layer
      Nov 25 '17 at 20:53













    up vote
    3
    down vote



    accepted







    up vote
    3
    down vote



    accepted






    The no-frills approach is to simply loop over the positional parameters, collecting all but -D into an array, and then use set -- to update the params:



    for param; do 
    [[ ! $param == '-D' ]] && newparams+=("$param")
    done
    set -- "$newparams[@]" # overwrites the original positional params





    share|improve this answer














    The no-frills approach is to simply loop over the positional parameters, collecting all but -D into an array, and then use set -- to update the params:



    for param; do 
    [[ ! $param == '-D' ]] && newparams+=("$param")
    done
    set -- "$newparams[@]" # overwrites the original positional params






    share|improve this answer














    share|improve this answer



    share|improve this answer








    edited Nov 12 '17 at 7:11

























    answered Nov 11 '17 at 12:00









    B Layer

    3,9241525




    3,9241525











    • In bash, you can even do newparams+=("$param").
      – choroba
      Nov 11 '17 at 12:13










    • Oh, yeah. I always forget if Bash has that or not. Thanks for the reminder.
      – B Layer
      Nov 11 '17 at 12:15











    • Downvoted because...why?
      – B Layer
      Nov 25 '17 at 20:53

















    • In bash, you can even do newparams+=("$param").
      – choroba
      Nov 11 '17 at 12:13










    • Oh, yeah. I always forget if Bash has that or not. Thanks for the reminder.
      – B Layer
      Nov 11 '17 at 12:15











    • Downvoted because...why?
      – B Layer
      Nov 25 '17 at 20:53
















    In bash, you can even do newparams+=("$param").
    – choroba
    Nov 11 '17 at 12:13




    In bash, you can even do newparams+=("$param").
    – choroba
    Nov 11 '17 at 12:13












    Oh, yeah. I always forget if Bash has that or not. Thanks for the reminder.
    – B Layer
    Nov 11 '17 at 12:15





    Oh, yeah. I always forget if Bash has that or not. Thanks for the reminder.
    – B Layer
    Nov 11 '17 at 12:15













    Downvoted because...why?
    – B Layer
    Nov 25 '17 at 20:53





    Downvoted because...why?
    – B Layer
    Nov 25 '17 at 20:53













    up vote
    4
    down vote













    With zsh, use the $array:#pattern parameter expansion operator:



    $ set foo -D -D bar '' $'anb'
    $ printf '<%s>n' "$@:#-D"
    <foo>
    <bar>
    <>
    <a
    b>


    POSIXly:



    for i do
    [ "$i" = -D ] || set -- "$@" "$i"
    shift
    done
    printf '<%s>n' "$@"


    BTW, you forgot the quotes, -- and -d:



    ls -ld -- "$@"


    If you want to sort by modification time, you can just use the -t option, here with -r (reverse) for oldest first:



    ls -lrtd -- "$@"


    Beware that if $ARGS is an empty array, it will list .. So you can do:



    [ "$@" -eq 0 ] || ls -lrtd -- "$@"


    To sort reliably based on the hour of the day irrespective of date, with zsh and a ls implementation that supports -U for not sorting:



    zmodload zsh/stat # best in ~/.zshrc
    bytime() zstat -LA REPLY -F%T +mtime -- $REPLY
    ls --full-time -ldU -- .(e'reply=("$@")'o+bytime)


    With limited shells like bash, it's very hard to sort files based on arbitrary metadata like that. Again, if you've got access to recent GNU tools, it's slightly easier:



    [ "$#" -gt 0 ] && (
    export LC_ALL=C
    printf '%s' "$@" |
    sed -z 's|^-$|./-|' |
    xargs -r0 stat --printf '%yt%n' -- |
    sort -zk2,2 |
    cut -zf 2-
    ) | xargs -r0 ls -lUd --


    Portably (but still using the non-standard ls -U here), it's generally easier to resort to perl, like:



    perl -MPOSIX -e '
    exec qwls -ldU --,
    map $_->[1]
    sort $a->[0] cmp $b->[0]
    map [strftime("%T", localtime((lstat$_)[9])), $_]
    @ARGV' -- "$@"





    share|improve this answer


























      up vote
      4
      down vote













      With zsh, use the $array:#pattern parameter expansion operator:



      $ set foo -D -D bar '' $'anb'
      $ printf '<%s>n' "$@:#-D"
      <foo>
      <bar>
      <>
      <a
      b>


      POSIXly:



      for i do
      [ "$i" = -D ] || set -- "$@" "$i"
      shift
      done
      printf '<%s>n' "$@"


      BTW, you forgot the quotes, -- and -d:



      ls -ld -- "$@"


      If you want to sort by modification time, you can just use the -t option, here with -r (reverse) for oldest first:



      ls -lrtd -- "$@"


      Beware that if $ARGS is an empty array, it will list .. So you can do:



      [ "$@" -eq 0 ] || ls -lrtd -- "$@"


      To sort reliably based on the hour of the day irrespective of date, with zsh and a ls implementation that supports -U for not sorting:



      zmodload zsh/stat # best in ~/.zshrc
      bytime() zstat -LA REPLY -F%T +mtime -- $REPLY
      ls --full-time -ldU -- .(e'reply=("$@")'o+bytime)


      With limited shells like bash, it's very hard to sort files based on arbitrary metadata like that. Again, if you've got access to recent GNU tools, it's slightly easier:



      [ "$#" -gt 0 ] && (
      export LC_ALL=C
      printf '%s' "$@" |
      sed -z 's|^-$|./-|' |
      xargs -r0 stat --printf '%yt%n' -- |
      sort -zk2,2 |
      cut -zf 2-
      ) | xargs -r0 ls -lUd --


      Portably (but still using the non-standard ls -U here), it's generally easier to resort to perl, like:



      perl -MPOSIX -e '
      exec qwls -ldU --,
      map $_->[1]
      sort $a->[0] cmp $b->[0]
      map [strftime("%T", localtime((lstat$_)[9])), $_]
      @ARGV' -- "$@"





      share|improve this answer
























        up vote
        4
        down vote










        up vote
        4
        down vote









        With zsh, use the $array:#pattern parameter expansion operator:



        $ set foo -D -D bar '' $'anb'
        $ printf '<%s>n' "$@:#-D"
        <foo>
        <bar>
        <>
        <a
        b>


        POSIXly:



        for i do
        [ "$i" = -D ] || set -- "$@" "$i"
        shift
        done
        printf '<%s>n' "$@"


        BTW, you forgot the quotes, -- and -d:



        ls -ld -- "$@"


        If you want to sort by modification time, you can just use the -t option, here with -r (reverse) for oldest first:



        ls -lrtd -- "$@"


        Beware that if $ARGS is an empty array, it will list .. So you can do:



        [ "$@" -eq 0 ] || ls -lrtd -- "$@"


        To sort reliably based on the hour of the day irrespective of date, with zsh and a ls implementation that supports -U for not sorting:



        zmodload zsh/stat # best in ~/.zshrc
        bytime() zstat -LA REPLY -F%T +mtime -- $REPLY
        ls --full-time -ldU -- .(e'reply=("$@")'o+bytime)


        With limited shells like bash, it's very hard to sort files based on arbitrary metadata like that. Again, if you've got access to recent GNU tools, it's slightly easier:



        [ "$#" -gt 0 ] && (
        export LC_ALL=C
        printf '%s' "$@" |
        sed -z 's|^-$|./-|' |
        xargs -r0 stat --printf '%yt%n' -- |
        sort -zk2,2 |
        cut -zf 2-
        ) | xargs -r0 ls -lUd --


        Portably (but still using the non-standard ls -U here), it's generally easier to resort to perl, like:



        perl -MPOSIX -e '
        exec qwls -ldU --,
        map $_->[1]
        sort $a->[0] cmp $b->[0]
        map [strftime("%T", localtime((lstat$_)[9])), $_]
        @ARGV' -- "$@"





        share|improve this answer














        With zsh, use the $array:#pattern parameter expansion operator:



        $ set foo -D -D bar '' $'anb'
        $ printf '<%s>n' "$@:#-D"
        <foo>
        <bar>
        <>
        <a
        b>


        POSIXly:



        for i do
        [ "$i" = -D ] || set -- "$@" "$i"
        shift
        done
        printf '<%s>n' "$@"


        BTW, you forgot the quotes, -- and -d:



        ls -ld -- "$@"


        If you want to sort by modification time, you can just use the -t option, here with -r (reverse) for oldest first:



        ls -lrtd -- "$@"


        Beware that if $ARGS is an empty array, it will list .. So you can do:



        [ "$@" -eq 0 ] || ls -lrtd -- "$@"


        To sort reliably based on the hour of the day irrespective of date, with zsh and a ls implementation that supports -U for not sorting:



        zmodload zsh/stat # best in ~/.zshrc
        bytime() zstat -LA REPLY -F%T +mtime -- $REPLY
        ls --full-time -ldU -- .(e'reply=("$@")'o+bytime)


        With limited shells like bash, it's very hard to sort files based on arbitrary metadata like that. Again, if you've got access to recent GNU tools, it's slightly easier:



        [ "$#" -gt 0 ] && (
        export LC_ALL=C
        printf '%s' "$@" |
        sed -z 's|^-$|./-|' |
        xargs -r0 stat --printf '%yt%n' -- |
        sort -zk2,2 |
        cut -zf 2-
        ) | xargs -r0 ls -lUd --


        Portably (but still using the non-standard ls -U here), it's generally easier to resort to perl, like:



        perl -MPOSIX -e '
        exec qwls -ldU --,
        map $_->[1]
        sort $a->[0] cmp $b->[0]
        map [strftime("%T", localtime((lstat$_)[9])), $_]
        @ARGV' -- "$@"






        share|improve this answer














        share|improve this answer



        share|improve this answer








        edited Nov 11 '17 at 14:47

























        answered Nov 11 '17 at 12:18









        Stéphane Chazelas

        283k53521854




        283k53521854



























             

            draft saved


            draft discarded















































             


            draft saved


            draft discarded














            StackExchange.ready(
            function ()
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f403890%2fhow-to-drop-an-argument-from-the-list-of-arguments-in-a-shell-script%23new-answer', 'question_page');

            );

            Post as a guest













































































            6x Zt pntskpdGCi,S6XvIW372ctaICQ6j PUwyi1auUXMVC Q7g14tCwJbMKRU,fy17uv6bDO0jU5rcI9shigv1CTwvJxc
            1,8,tIK 8oiZyUuoC2qVdWoe0sVAZXYWFnd7SfOo4kAUC,r 7PMXJZ2emFOyRFFGSz8X3xhK

            Popular posts from this blog

            How to check contact read email or not when send email to Individual?

            How many registers does an x86_64 CPU actually have?

            Displaying single band from multi-band raster using QGIS