Kernel.Panic
Kernel.Panic

Reputation: 3

This simple bash script doesn't work. What am I doing wrong?

I'm trying to create the script that will simply do cd ../ times n, where n is whatever I pass to it, or 1 by default:

STEPS=${1:-1}
for i in $STEPS; do
    cd ..
done

It doesn't give me any errors and it does nothing..

Upvotes: 0

Views: 612

Answers (3)

chepner
chepner

Reputation: 532418

In bash, you generally don't want to generate a sequence of numbers to iterate over. Use the C-style for loop:

for ((i=1; i<=$STEPS; i++)); do
  cd ..
done

If this is in a file, you need to source it ( . ./cd-up) rather than executing it (sh ./cd-up or ./cd-up, etc).

If you are, in fact, using zsh, you can simply use the repeat construct:

repeat $STEPS do cd ..; done

or its shorter form for simple commands

repeat $STEPS cd ..

Upvotes: 1

Matthias
Matthias

Reputation: 4000

You should be able to source it to do what you wish, e.g.

. yourscript.sh 3

to change directory 3 times. (notice the dot before the yourscript.sh)

After you fix the script at least, e.g.

#!/bin/bash
STEPS=$1
for ((i=1; i<=$STEPS; i++)); do
  cd ..
done

Thanks @Charles Duffy for mentioning sourcing, and thanks @chepner for the fixed for loop.

Some info:

Shell scripts are run inside a subshell, and each subshell has its own concept of what the current directory is. The cd succeeds, but as soon as the subshell exits, you're back in the interactive shell and nothing ever changed there.

from here

Upvotes: 3

Tom Fenech
Tom Fenech

Reputation: 74705

Assuming that $STEPS is always a single number, then your for loop will only run for one iteration. This is because the type of loop that you're using expects a list of words:

for name in word1 word2 word3; do
    # some stuff
done

This will run three times, assigning each value in the list to variable $name.

Using a C-style loop, you could do this:

steps=${1:-1}
for (( i = 0; i < steps; ++i )); do
    cd ..
done

Alternatively, in any POSIX shell you can use a while loop:

steps=${1:-1}
while [ $steps -gt 0 ]; do
    cd ..
    steps=$(( steps - 1 ))
done

If you pass in something that's not an integer, then neither of these approaches will work!


Remember that if you run this as a script, it will change the directory while the script is running but the parent shell (the one you ran the script from) will be unaffected.

Upvotes: 0

Related Questions