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

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













































































            Popular posts from this blog

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

            Bahrain

            Postfix configuration issue with fips on centos 7; mailgun relay