Problem with shift in bash












2















Tried to use a wrapper around find but hitting the following problem. I want e.g to provide a few directories as arguments but the last argument is always a number that indicates how old data should be removed. For example:



rmoldfiles dir1 dir2 dir3 20


This should remove the old files that are older than 30 days looking at mtime of course



Here is the script:



#!/bin/bash

die()
{
echo >&2 "$@"
exit 1
}

usage()
{
echo >&2 "Usage: $0 [dir1 dir2 dir3] [days old]"
die
}

if [[ (($# < 1)) || -f "$1" ]]; then
if [[ -f "$1" ]]; then
printf '%sn' "Please provide a directory"
fi
usage
fi

while (( $# )); do
while IFS= read -r -d $'' file; do
printf 'rm %sn' "$file"
sleep 1
done < <(find "$1" -type f -mtime +$2 -print0)
shift
done

echo "Done deleting"


Problem



How to shift directories but not the last argument.










share|improve this question




















  • 1





    Is there a reason that the number of days needs to be the last argument? Could you make it the first argument instead? Or could you make it a switch or flag instead of an argument (and use something like getopt to parse arguments/switches/flags)?

    – jayhendren
    Dec 20 '18 at 18:43











  • @jayhendren I thought about getopts but I wanted not to overcomplicate this so thought just use "$1" for directories and shift , then use "$2"` for -mtime `

    – holasz
    Dec 20 '18 at 18:47











  • consider also a simplification of your while find loop: find "$1" -type f -mtime +"$2" -printf rm '%pn' -delete (assuming GNU find, as per the -print0)

    – Jeff Schaller
    Dec 20 '18 at 18:56


















2















Tried to use a wrapper around find but hitting the following problem. I want e.g to provide a few directories as arguments but the last argument is always a number that indicates how old data should be removed. For example:



rmoldfiles dir1 dir2 dir3 20


This should remove the old files that are older than 30 days looking at mtime of course



Here is the script:



#!/bin/bash

die()
{
echo >&2 "$@"
exit 1
}

usage()
{
echo >&2 "Usage: $0 [dir1 dir2 dir3] [days old]"
die
}

if [[ (($# < 1)) || -f "$1" ]]; then
if [[ -f "$1" ]]; then
printf '%sn' "Please provide a directory"
fi
usage
fi

while (( $# )); do
while IFS= read -r -d $'' file; do
printf 'rm %sn' "$file"
sleep 1
done < <(find "$1" -type f -mtime +$2 -print0)
shift
done

echo "Done deleting"


Problem



How to shift directories but not the last argument.










share|improve this question




















  • 1





    Is there a reason that the number of days needs to be the last argument? Could you make it the first argument instead? Or could you make it a switch or flag instead of an argument (and use something like getopt to parse arguments/switches/flags)?

    – jayhendren
    Dec 20 '18 at 18:43











  • @jayhendren I thought about getopts but I wanted not to overcomplicate this so thought just use "$1" for directories and shift , then use "$2"` for -mtime `

    – holasz
    Dec 20 '18 at 18:47











  • consider also a simplification of your while find loop: find "$1" -type f -mtime +"$2" -printf rm '%pn' -delete (assuming GNU find, as per the -print0)

    – Jeff Schaller
    Dec 20 '18 at 18:56
















2












2








2








Tried to use a wrapper around find but hitting the following problem. I want e.g to provide a few directories as arguments but the last argument is always a number that indicates how old data should be removed. For example:



rmoldfiles dir1 dir2 dir3 20


This should remove the old files that are older than 30 days looking at mtime of course



Here is the script:



#!/bin/bash

die()
{
echo >&2 "$@"
exit 1
}

usage()
{
echo >&2 "Usage: $0 [dir1 dir2 dir3] [days old]"
die
}

if [[ (($# < 1)) || -f "$1" ]]; then
if [[ -f "$1" ]]; then
printf '%sn' "Please provide a directory"
fi
usage
fi

while (( $# )); do
while IFS= read -r -d $'' file; do
printf 'rm %sn' "$file"
sleep 1
done < <(find "$1" -type f -mtime +$2 -print0)
shift
done

echo "Done deleting"


Problem



How to shift directories but not the last argument.










share|improve this question
















Tried to use a wrapper around find but hitting the following problem. I want e.g to provide a few directories as arguments but the last argument is always a number that indicates how old data should be removed. For example:



rmoldfiles dir1 dir2 dir3 20


This should remove the old files that are older than 30 days looking at mtime of course



Here is the script:



#!/bin/bash

die()
{
echo >&2 "$@"
exit 1
}

usage()
{
echo >&2 "Usage: $0 [dir1 dir2 dir3] [days old]"
die
}

if [[ (($# < 1)) || -f "$1" ]]; then
if [[ -f "$1" ]]; then
printf '%sn' "Please provide a directory"
fi
usage
fi

while (( $# )); do
while IFS= read -r -d $'' file; do
printf 'rm %sn' "$file"
sleep 1
done < <(find "$1" -type f -mtime +$2 -print0)
shift
done

echo "Done deleting"


Problem



How to shift directories but not the last argument.







bash shell






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Dec 20 '18 at 19:08









Rui F Ribeiro

39.7k1479132




39.7k1479132










asked Dec 20 '18 at 18:39









holaszholasz

158212




158212








  • 1





    Is there a reason that the number of days needs to be the last argument? Could you make it the first argument instead? Or could you make it a switch or flag instead of an argument (and use something like getopt to parse arguments/switches/flags)?

    – jayhendren
    Dec 20 '18 at 18:43











  • @jayhendren I thought about getopts but I wanted not to overcomplicate this so thought just use "$1" for directories and shift , then use "$2"` for -mtime `

    – holasz
    Dec 20 '18 at 18:47











  • consider also a simplification of your while find loop: find "$1" -type f -mtime +"$2" -printf rm '%pn' -delete (assuming GNU find, as per the -print0)

    – Jeff Schaller
    Dec 20 '18 at 18:56
















  • 1





    Is there a reason that the number of days needs to be the last argument? Could you make it the first argument instead? Or could you make it a switch or flag instead of an argument (and use something like getopt to parse arguments/switches/flags)?

    – jayhendren
    Dec 20 '18 at 18:43











  • @jayhendren I thought about getopts but I wanted not to overcomplicate this so thought just use "$1" for directories and shift , then use "$2"` for -mtime `

    – holasz
    Dec 20 '18 at 18:47











  • consider also a simplification of your while find loop: find "$1" -type f -mtime +"$2" -printf rm '%pn' -delete (assuming GNU find, as per the -print0)

    – Jeff Schaller
    Dec 20 '18 at 18:56










1




1





Is there a reason that the number of days needs to be the last argument? Could you make it the first argument instead? Or could you make it a switch or flag instead of an argument (and use something like getopt to parse arguments/switches/flags)?

– jayhendren
Dec 20 '18 at 18:43





Is there a reason that the number of days needs to be the last argument? Could you make it the first argument instead? Or could you make it a switch or flag instead of an argument (and use something like getopt to parse arguments/switches/flags)?

– jayhendren
Dec 20 '18 at 18:43













@jayhendren I thought about getopts but I wanted not to overcomplicate this so thought just use "$1" for directories and shift , then use "$2"` for -mtime `

– holasz
Dec 20 '18 at 18:47





@jayhendren I thought about getopts but I wanted not to overcomplicate this so thought just use "$1" for directories and shift , then use "$2"` for -mtime `

– holasz
Dec 20 '18 at 18:47













consider also a simplification of your while find loop: find "$1" -type f -mtime +"$2" -printf rm '%pn' -delete (assuming GNU find, as per the -print0)

– Jeff Schaller
Dec 20 '18 at 18:56







consider also a simplification of your while find loop: find "$1" -type f -mtime +"$2" -printf rm '%pn' -delete (assuming GNU find, as per the -print0)

– Jeff Schaller
Dec 20 '18 at 18:56












3 Answers
3






active

oldest

votes


















5














A couple of solutions.





  1. Pick out the last command line argument.



    args=( "$@" )
    num=${args[-1]}
    args=( "${args[@]:0:${#args[@]} - 1}" )


    (then use find "${args[@]}" -type f -mtime "+$num" -print -delete to delete those files).




  2. Put the number first.



     num=$1; shift


    (then use find "$@" -type f -mtime "+$num" -print -delete to delete the files).




The loop is only needed if you have hundreds or thousands of directories to process, in which case the find command would be too long with a single invocation. Otherwise, don't loop. find can take multiple search paths.



If you want to insert a delay and use rm explicitly, and have some formatted output for each file:



find "$@" -type f -mtime "+$num" -exec sh -c '
for pathname do
printf "Removing %sn" "$pathname"
rm -- "$pathname"
sleep 1
done' sh {} +


If you find that you do need to loop over the directories (or if this just feels better):



# Assumes that the arguments are in the order
# num dir1 dir2 dir3 ...

num=$1
shift

for dir do
printf 'Processing %s...n' "$dir"

find "$dir" -type f -mtime "+$num" -exec sh -c '
for pathname do
printf "Removing %sn" "$pathname"
rm -- "$pathname"
sleep 1
done' sh {} +
done


or,



# Assumes that the arguments are in the order
# dir1 dir2 dir3 ... num

args=( "$@" )
num=${args[-1]}
args=( "${args[@]:0:${#args[@]} - 1}" )

for dir in "${args[@]}"; do

# as above

done





share|improve this answer


























  • Kusalananda where to put this "+$num" in your last piece of code?

    – holasz
    Dec 20 '18 at 19:14











  • @holasz Sorry, the last code snippets assume that you pass the number as the firs argument (because its easiest) and then pick that out into $num and shift it off. I'll update after my supper.

    – Kusalananda
    Dec 20 '18 at 19:17











  • Kusalandela ok your last code works when using e.g rmoldfiles 27 dir1 dir2 dir3 ... Is there a way to use argument as last dir?

    – holasz
    Dec 20 '18 at 19:23











  • @holasz see first part of answer. I'll update soon.

    – Kusalananda
    Dec 20 '18 at 19:35











  • @holasz See updated answer.

    – Kusalananda
    Dec 20 '18 at 19:52



















3














Since you're only expecting (and providing) three directories before the age parameter, don't loop indiscriminately; instead, loop explicitly:



for dir in 1 2 3; do
# work with "$1"
shift
done


or stop looping when there's one parameter left:



while [ "$#" -gt 1 ]; do
echo "Work with $1"
shift;
done


Since the "days" parameter moves during each shift, you'll need to save it off initially:



days=$4


... before calling the loop.



... and if you allow for an arbitrary number of directories to be passed:



[ "$#" -gt 1 ] || exit 1
days=${@: -1}
while [ "$#" -gt 1 ]; do
echo work with "$1" and "$days"
shift
done


This uses the bash array $@ and asks for the last element of it (indicated by -1, separated by a space to prevent it from being interpreted as a modifier to :); it then loops over the parameters one by one until there's one left (the initial 'day' parameter at the end).






share|improve this answer


























  • There is no limiti. I used 3 dirs as an example but there could be 2 dirs or 5. But if I use shift this way then $2 isn't having the value that should be passed to mtime

    – holasz
    Dec 20 '18 at 18:49











  • I've extended the answer to allow an arbitrary number of directories

    – Jeff Schaller
    Dec 20 '18 at 18:53











  • it almost works but $days are also dragged with the dirs and the script says 27 no such file or directory and the script continues

    – holasz
    Dec 20 '18 at 19:15











  • can you show how you called the code? if the "days" value is at the end of the argument list, it won't ever be used inside the loop as a "$1" parameter

    – Jeff Schaller
    Dec 20 '18 at 19:18






  • 1





    Jeff it works now! THank you very much. I learned a lot today!

    – holasz
    Dec 20 '18 at 19:58



















0














Just change (( $# )) to (( $# > 1)):



while (( $# > 1 )); do
echo "file is: $1"
done

echo "days are: $1"





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',
    autoActivateHeartbeat: false,
    convertImagesToLinks: false,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: null,
    bindNavPrevention: true,
    postfix: "",
    imageUploader: {
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    },
    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%2f490178%2fproblem-with-shift-in-bash%23new-answer', 'question_page');
    }
    );

    Post as a guest















    Required, but never shown

























    3 Answers
    3






    active

    oldest

    votes








    3 Answers
    3






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    5














    A couple of solutions.





    1. Pick out the last command line argument.



      args=( "$@" )
      num=${args[-1]}
      args=( "${args[@]:0:${#args[@]} - 1}" )


      (then use find "${args[@]}" -type f -mtime "+$num" -print -delete to delete those files).




    2. Put the number first.



       num=$1; shift


      (then use find "$@" -type f -mtime "+$num" -print -delete to delete the files).




    The loop is only needed if you have hundreds or thousands of directories to process, in which case the find command would be too long with a single invocation. Otherwise, don't loop. find can take multiple search paths.



    If you want to insert a delay and use rm explicitly, and have some formatted output for each file:



    find "$@" -type f -mtime "+$num" -exec sh -c '
    for pathname do
    printf "Removing %sn" "$pathname"
    rm -- "$pathname"
    sleep 1
    done' sh {} +


    If you find that you do need to loop over the directories (or if this just feels better):



    # Assumes that the arguments are in the order
    # num dir1 dir2 dir3 ...

    num=$1
    shift

    for dir do
    printf 'Processing %s...n' "$dir"

    find "$dir" -type f -mtime "+$num" -exec sh -c '
    for pathname do
    printf "Removing %sn" "$pathname"
    rm -- "$pathname"
    sleep 1
    done' sh {} +
    done


    or,



    # Assumes that the arguments are in the order
    # dir1 dir2 dir3 ... num

    args=( "$@" )
    num=${args[-1]}
    args=( "${args[@]:0:${#args[@]} - 1}" )

    for dir in "${args[@]}"; do

    # as above

    done





    share|improve this answer


























    • Kusalananda where to put this "+$num" in your last piece of code?

      – holasz
      Dec 20 '18 at 19:14











    • @holasz Sorry, the last code snippets assume that you pass the number as the firs argument (because its easiest) and then pick that out into $num and shift it off. I'll update after my supper.

      – Kusalananda
      Dec 20 '18 at 19:17











    • Kusalandela ok your last code works when using e.g rmoldfiles 27 dir1 dir2 dir3 ... Is there a way to use argument as last dir?

      – holasz
      Dec 20 '18 at 19:23











    • @holasz see first part of answer. I'll update soon.

      – Kusalananda
      Dec 20 '18 at 19:35











    • @holasz See updated answer.

      – Kusalananda
      Dec 20 '18 at 19:52
















    5














    A couple of solutions.





    1. Pick out the last command line argument.



      args=( "$@" )
      num=${args[-1]}
      args=( "${args[@]:0:${#args[@]} - 1}" )


      (then use find "${args[@]}" -type f -mtime "+$num" -print -delete to delete those files).




    2. Put the number first.



       num=$1; shift


      (then use find "$@" -type f -mtime "+$num" -print -delete to delete the files).




    The loop is only needed if you have hundreds or thousands of directories to process, in which case the find command would be too long with a single invocation. Otherwise, don't loop. find can take multiple search paths.



    If you want to insert a delay and use rm explicitly, and have some formatted output for each file:



    find "$@" -type f -mtime "+$num" -exec sh -c '
    for pathname do
    printf "Removing %sn" "$pathname"
    rm -- "$pathname"
    sleep 1
    done' sh {} +


    If you find that you do need to loop over the directories (or if this just feels better):



    # Assumes that the arguments are in the order
    # num dir1 dir2 dir3 ...

    num=$1
    shift

    for dir do
    printf 'Processing %s...n' "$dir"

    find "$dir" -type f -mtime "+$num" -exec sh -c '
    for pathname do
    printf "Removing %sn" "$pathname"
    rm -- "$pathname"
    sleep 1
    done' sh {} +
    done


    or,



    # Assumes that the arguments are in the order
    # dir1 dir2 dir3 ... num

    args=( "$@" )
    num=${args[-1]}
    args=( "${args[@]:0:${#args[@]} - 1}" )

    for dir in "${args[@]}"; do

    # as above

    done





    share|improve this answer


























    • Kusalananda where to put this "+$num" in your last piece of code?

      – holasz
      Dec 20 '18 at 19:14











    • @holasz Sorry, the last code snippets assume that you pass the number as the firs argument (because its easiest) and then pick that out into $num and shift it off. I'll update after my supper.

      – Kusalananda
      Dec 20 '18 at 19:17











    • Kusalandela ok your last code works when using e.g rmoldfiles 27 dir1 dir2 dir3 ... Is there a way to use argument as last dir?

      – holasz
      Dec 20 '18 at 19:23











    • @holasz see first part of answer. I'll update soon.

      – Kusalananda
      Dec 20 '18 at 19:35











    • @holasz See updated answer.

      – Kusalananda
      Dec 20 '18 at 19:52














    5












    5








    5







    A couple of solutions.





    1. Pick out the last command line argument.



      args=( "$@" )
      num=${args[-1]}
      args=( "${args[@]:0:${#args[@]} - 1}" )


      (then use find "${args[@]}" -type f -mtime "+$num" -print -delete to delete those files).




    2. Put the number first.



       num=$1; shift


      (then use find "$@" -type f -mtime "+$num" -print -delete to delete the files).




    The loop is only needed if you have hundreds or thousands of directories to process, in which case the find command would be too long with a single invocation. Otherwise, don't loop. find can take multiple search paths.



    If you want to insert a delay and use rm explicitly, and have some formatted output for each file:



    find "$@" -type f -mtime "+$num" -exec sh -c '
    for pathname do
    printf "Removing %sn" "$pathname"
    rm -- "$pathname"
    sleep 1
    done' sh {} +


    If you find that you do need to loop over the directories (or if this just feels better):



    # Assumes that the arguments are in the order
    # num dir1 dir2 dir3 ...

    num=$1
    shift

    for dir do
    printf 'Processing %s...n' "$dir"

    find "$dir" -type f -mtime "+$num" -exec sh -c '
    for pathname do
    printf "Removing %sn" "$pathname"
    rm -- "$pathname"
    sleep 1
    done' sh {} +
    done


    or,



    # Assumes that the arguments are in the order
    # dir1 dir2 dir3 ... num

    args=( "$@" )
    num=${args[-1]}
    args=( "${args[@]:0:${#args[@]} - 1}" )

    for dir in "${args[@]}"; do

    # as above

    done





    share|improve this answer















    A couple of solutions.





    1. Pick out the last command line argument.



      args=( "$@" )
      num=${args[-1]}
      args=( "${args[@]:0:${#args[@]} - 1}" )


      (then use find "${args[@]}" -type f -mtime "+$num" -print -delete to delete those files).




    2. Put the number first.



       num=$1; shift


      (then use find "$@" -type f -mtime "+$num" -print -delete to delete the files).




    The loop is only needed if you have hundreds or thousands of directories to process, in which case the find command would be too long with a single invocation. Otherwise, don't loop. find can take multiple search paths.



    If you want to insert a delay and use rm explicitly, and have some formatted output for each file:



    find "$@" -type f -mtime "+$num" -exec sh -c '
    for pathname do
    printf "Removing %sn" "$pathname"
    rm -- "$pathname"
    sleep 1
    done' sh {} +


    If you find that you do need to loop over the directories (or if this just feels better):



    # Assumes that the arguments are in the order
    # num dir1 dir2 dir3 ...

    num=$1
    shift

    for dir do
    printf 'Processing %s...n' "$dir"

    find "$dir" -type f -mtime "+$num" -exec sh -c '
    for pathname do
    printf "Removing %sn" "$pathname"
    rm -- "$pathname"
    sleep 1
    done' sh {} +
    done


    or,



    # Assumes that the arguments are in the order
    # dir1 dir2 dir3 ... num

    args=( "$@" )
    num=${args[-1]}
    args=( "${args[@]:0:${#args[@]} - 1}" )

    for dir in "${args[@]}"; do

    # as above

    done






    share|improve this answer














    share|improve this answer



    share|improve this answer








    edited Dec 20 '18 at 19:52

























    answered Dec 20 '18 at 18:51









    KusalanandaKusalananda

    127k16239394




    127k16239394













    • Kusalananda where to put this "+$num" in your last piece of code?

      – holasz
      Dec 20 '18 at 19:14











    • @holasz Sorry, the last code snippets assume that you pass the number as the firs argument (because its easiest) and then pick that out into $num and shift it off. I'll update after my supper.

      – Kusalananda
      Dec 20 '18 at 19:17











    • Kusalandela ok your last code works when using e.g rmoldfiles 27 dir1 dir2 dir3 ... Is there a way to use argument as last dir?

      – holasz
      Dec 20 '18 at 19:23











    • @holasz see first part of answer. I'll update soon.

      – Kusalananda
      Dec 20 '18 at 19:35











    • @holasz See updated answer.

      – Kusalananda
      Dec 20 '18 at 19:52



















    • Kusalananda where to put this "+$num" in your last piece of code?

      – holasz
      Dec 20 '18 at 19:14











    • @holasz Sorry, the last code snippets assume that you pass the number as the firs argument (because its easiest) and then pick that out into $num and shift it off. I'll update after my supper.

      – Kusalananda
      Dec 20 '18 at 19:17











    • Kusalandela ok your last code works when using e.g rmoldfiles 27 dir1 dir2 dir3 ... Is there a way to use argument as last dir?

      – holasz
      Dec 20 '18 at 19:23











    • @holasz see first part of answer. I'll update soon.

      – Kusalananda
      Dec 20 '18 at 19:35











    • @holasz See updated answer.

      – Kusalananda
      Dec 20 '18 at 19:52

















    Kusalananda where to put this "+$num" in your last piece of code?

    – holasz
    Dec 20 '18 at 19:14





    Kusalananda where to put this "+$num" in your last piece of code?

    – holasz
    Dec 20 '18 at 19:14













    @holasz Sorry, the last code snippets assume that you pass the number as the firs argument (because its easiest) and then pick that out into $num and shift it off. I'll update after my supper.

    – Kusalananda
    Dec 20 '18 at 19:17





    @holasz Sorry, the last code snippets assume that you pass the number as the firs argument (because its easiest) and then pick that out into $num and shift it off. I'll update after my supper.

    – Kusalananda
    Dec 20 '18 at 19:17













    Kusalandela ok your last code works when using e.g rmoldfiles 27 dir1 dir2 dir3 ... Is there a way to use argument as last dir?

    – holasz
    Dec 20 '18 at 19:23





    Kusalandela ok your last code works when using e.g rmoldfiles 27 dir1 dir2 dir3 ... Is there a way to use argument as last dir?

    – holasz
    Dec 20 '18 at 19:23













    @holasz see first part of answer. I'll update soon.

    – Kusalananda
    Dec 20 '18 at 19:35





    @holasz see first part of answer. I'll update soon.

    – Kusalananda
    Dec 20 '18 at 19:35













    @holasz See updated answer.

    – Kusalananda
    Dec 20 '18 at 19:52





    @holasz See updated answer.

    – Kusalananda
    Dec 20 '18 at 19:52













    3














    Since you're only expecting (and providing) three directories before the age parameter, don't loop indiscriminately; instead, loop explicitly:



    for dir in 1 2 3; do
    # work with "$1"
    shift
    done


    or stop looping when there's one parameter left:



    while [ "$#" -gt 1 ]; do
    echo "Work with $1"
    shift;
    done


    Since the "days" parameter moves during each shift, you'll need to save it off initially:



    days=$4


    ... before calling the loop.



    ... and if you allow for an arbitrary number of directories to be passed:



    [ "$#" -gt 1 ] || exit 1
    days=${@: -1}
    while [ "$#" -gt 1 ]; do
    echo work with "$1" and "$days"
    shift
    done


    This uses the bash array $@ and asks for the last element of it (indicated by -1, separated by a space to prevent it from being interpreted as a modifier to :); it then loops over the parameters one by one until there's one left (the initial 'day' parameter at the end).






    share|improve this answer


























    • There is no limiti. I used 3 dirs as an example but there could be 2 dirs or 5. But if I use shift this way then $2 isn't having the value that should be passed to mtime

      – holasz
      Dec 20 '18 at 18:49











    • I've extended the answer to allow an arbitrary number of directories

      – Jeff Schaller
      Dec 20 '18 at 18:53











    • it almost works but $days are also dragged with the dirs and the script says 27 no such file or directory and the script continues

      – holasz
      Dec 20 '18 at 19:15











    • can you show how you called the code? if the "days" value is at the end of the argument list, it won't ever be used inside the loop as a "$1" parameter

      – Jeff Schaller
      Dec 20 '18 at 19:18






    • 1





      Jeff it works now! THank you very much. I learned a lot today!

      – holasz
      Dec 20 '18 at 19:58
















    3














    Since you're only expecting (and providing) three directories before the age parameter, don't loop indiscriminately; instead, loop explicitly:



    for dir in 1 2 3; do
    # work with "$1"
    shift
    done


    or stop looping when there's one parameter left:



    while [ "$#" -gt 1 ]; do
    echo "Work with $1"
    shift;
    done


    Since the "days" parameter moves during each shift, you'll need to save it off initially:



    days=$4


    ... before calling the loop.



    ... and if you allow for an arbitrary number of directories to be passed:



    [ "$#" -gt 1 ] || exit 1
    days=${@: -1}
    while [ "$#" -gt 1 ]; do
    echo work with "$1" and "$days"
    shift
    done


    This uses the bash array $@ and asks for the last element of it (indicated by -1, separated by a space to prevent it from being interpreted as a modifier to :); it then loops over the parameters one by one until there's one left (the initial 'day' parameter at the end).






    share|improve this answer


























    • There is no limiti. I used 3 dirs as an example but there could be 2 dirs or 5. But if I use shift this way then $2 isn't having the value that should be passed to mtime

      – holasz
      Dec 20 '18 at 18:49











    • I've extended the answer to allow an arbitrary number of directories

      – Jeff Schaller
      Dec 20 '18 at 18:53











    • it almost works but $days are also dragged with the dirs and the script says 27 no such file or directory and the script continues

      – holasz
      Dec 20 '18 at 19:15











    • can you show how you called the code? if the "days" value is at the end of the argument list, it won't ever be used inside the loop as a "$1" parameter

      – Jeff Schaller
      Dec 20 '18 at 19:18






    • 1





      Jeff it works now! THank you very much. I learned a lot today!

      – holasz
      Dec 20 '18 at 19:58














    3












    3








    3







    Since you're only expecting (and providing) three directories before the age parameter, don't loop indiscriminately; instead, loop explicitly:



    for dir in 1 2 3; do
    # work with "$1"
    shift
    done


    or stop looping when there's one parameter left:



    while [ "$#" -gt 1 ]; do
    echo "Work with $1"
    shift;
    done


    Since the "days" parameter moves during each shift, you'll need to save it off initially:



    days=$4


    ... before calling the loop.



    ... and if you allow for an arbitrary number of directories to be passed:



    [ "$#" -gt 1 ] || exit 1
    days=${@: -1}
    while [ "$#" -gt 1 ]; do
    echo work with "$1" and "$days"
    shift
    done


    This uses the bash array $@ and asks for the last element of it (indicated by -1, separated by a space to prevent it from being interpreted as a modifier to :); it then loops over the parameters one by one until there's one left (the initial 'day' parameter at the end).






    share|improve this answer















    Since you're only expecting (and providing) three directories before the age parameter, don't loop indiscriminately; instead, loop explicitly:



    for dir in 1 2 3; do
    # work with "$1"
    shift
    done


    or stop looping when there's one parameter left:



    while [ "$#" -gt 1 ]; do
    echo "Work with $1"
    shift;
    done


    Since the "days" parameter moves during each shift, you'll need to save it off initially:



    days=$4


    ... before calling the loop.



    ... and if you allow for an arbitrary number of directories to be passed:



    [ "$#" -gt 1 ] || exit 1
    days=${@: -1}
    while [ "$#" -gt 1 ]; do
    echo work with "$1" and "$days"
    shift
    done


    This uses the bash array $@ and asks for the last element of it (indicated by -1, separated by a space to prevent it from being interpreted as a modifier to :); it then loops over the parameters one by one until there's one left (the initial 'day' parameter at the end).







    share|improve this answer














    share|improve this answer



    share|improve this answer








    edited Dec 20 '18 at 19:08

























    answered Dec 20 '18 at 18:46









    Jeff SchallerJeff Schaller

    40.6k1056129




    40.6k1056129













    • There is no limiti. I used 3 dirs as an example but there could be 2 dirs or 5. But if I use shift this way then $2 isn't having the value that should be passed to mtime

      – holasz
      Dec 20 '18 at 18:49











    • I've extended the answer to allow an arbitrary number of directories

      – Jeff Schaller
      Dec 20 '18 at 18:53











    • it almost works but $days are also dragged with the dirs and the script says 27 no such file or directory and the script continues

      – holasz
      Dec 20 '18 at 19:15











    • can you show how you called the code? if the "days" value is at the end of the argument list, it won't ever be used inside the loop as a "$1" parameter

      – Jeff Schaller
      Dec 20 '18 at 19:18






    • 1





      Jeff it works now! THank you very much. I learned a lot today!

      – holasz
      Dec 20 '18 at 19:58



















    • There is no limiti. I used 3 dirs as an example but there could be 2 dirs or 5. But if I use shift this way then $2 isn't having the value that should be passed to mtime

      – holasz
      Dec 20 '18 at 18:49











    • I've extended the answer to allow an arbitrary number of directories

      – Jeff Schaller
      Dec 20 '18 at 18:53











    • it almost works but $days are also dragged with the dirs and the script says 27 no such file or directory and the script continues

      – holasz
      Dec 20 '18 at 19:15











    • can you show how you called the code? if the "days" value is at the end of the argument list, it won't ever be used inside the loop as a "$1" parameter

      – Jeff Schaller
      Dec 20 '18 at 19:18






    • 1





      Jeff it works now! THank you very much. I learned a lot today!

      – holasz
      Dec 20 '18 at 19:58

















    There is no limiti. I used 3 dirs as an example but there could be 2 dirs or 5. But if I use shift this way then $2 isn't having the value that should be passed to mtime

    – holasz
    Dec 20 '18 at 18:49





    There is no limiti. I used 3 dirs as an example but there could be 2 dirs or 5. But if I use shift this way then $2 isn't having the value that should be passed to mtime

    – holasz
    Dec 20 '18 at 18:49













    I've extended the answer to allow an arbitrary number of directories

    – Jeff Schaller
    Dec 20 '18 at 18:53





    I've extended the answer to allow an arbitrary number of directories

    – Jeff Schaller
    Dec 20 '18 at 18:53













    it almost works but $days are also dragged with the dirs and the script says 27 no such file or directory and the script continues

    – holasz
    Dec 20 '18 at 19:15





    it almost works but $days are also dragged with the dirs and the script says 27 no such file or directory and the script continues

    – holasz
    Dec 20 '18 at 19:15













    can you show how you called the code? if the "days" value is at the end of the argument list, it won't ever be used inside the loop as a "$1" parameter

    – Jeff Schaller
    Dec 20 '18 at 19:18





    can you show how you called the code? if the "days" value is at the end of the argument list, it won't ever be used inside the loop as a "$1" parameter

    – Jeff Schaller
    Dec 20 '18 at 19:18




    1




    1





    Jeff it works now! THank you very much. I learned a lot today!

    – holasz
    Dec 20 '18 at 19:58





    Jeff it works now! THank you very much. I learned a lot today!

    – holasz
    Dec 20 '18 at 19:58











    0














    Just change (( $# )) to (( $# > 1)):



    while (( $# > 1 )); do
    echo "file is: $1"
    done

    echo "days are: $1"





    share|improve this answer




























      0














      Just change (( $# )) to (( $# > 1)):



      while (( $# > 1 )); do
      echo "file is: $1"
      done

      echo "days are: $1"





      share|improve this answer


























        0












        0








        0







        Just change (( $# )) to (( $# > 1)):



        while (( $# > 1 )); do
        echo "file is: $1"
        done

        echo "days are: $1"





        share|improve this answer













        Just change (( $# )) to (( $# > 1)):



        while (( $# > 1 )); do
        echo "file is: $1"
        done

        echo "days are: $1"






        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered Dec 20 '18 at 18:47









        jayhendrenjayhendren

        5,40721444




        5,40721444






























            draft saved

            draft discarded




















































            Thanks for contributing an answer to Unix & Linux Stack Exchange!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid



            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.


            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f490178%2fproblem-with-shift-in-bash%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            Popular posts from this blog

            Bressuire

            Cabo Verde

            Gyllenstierna