3

So after an uncomfortable number of hours of trying to do this, this is what I'm trying to do:

Write a bash shell script called direct.sh. This script will take an arbitrary number of command line arguments. Your script should create directories starting with the first argument, then the second directory inside the first one, and then the next one inside the second one, and so on.

For e.g. direct.sh dir1 dir2 dir3

should first create dir1, then create dir1/dir2, then finally create dir1/dir2/dir3

This is what I have done after 20 hours.

#!/bin/bash
   
   for i in $@
   do
           mkdir -p $1/$i
   done

I know its wrong. Please help.

2
  • 3
    for i in "$@"; do mkdir -p "$i" && cd "$i"; done Since you are using individual arguments, you need to create a directory and then change to it before creating the next. Your other option is to build one string from all arguments with directory separators between the names and call mkdir -p once. ALWAYS QUOTE YOUR VARIABLES. Commented Nov 23, 2020 at 5:39
  • AND learn how to debug your code. If you had added echo '$1/$i='"$1/$i" you would have understood your logic error. You can also use set -x before a line/block of code that is causing your problems so you can see what values variables are set too. Use set +x to turn it off later in the script. Good luck. Commented Nov 23, 2020 at 6:01

3 Answers 3

6

This can be done in a single step, since mkdir -p will create all needed parent directories on the way (that's what the -p option does).

#!/bin/bash
IFS=/
mkdir -p "$*"

Explanation: $* expands to all of the script's arguments, spliced together into a single string, separated by the first character of IFS. That's normally a space character, but here it's set to "/" instead. The double-quotes around it prevent unexpected word-splitting or wildcard expansion.

So, if you run direct.sh dir1 dir2 dir3, it executes mkdir -p "dir1/dir2/dir3", which creates all 3 directory levels (or at least, those that don't already exist).

BTW, in general you should set IFS back to normal after changing it like this. But since there's nothing afterward in the script that might get messed up, and changing it in a script doesn't affect the parent process (the shell you used to run the script), there's no need to set it back in this case.

Sign up to request clarification or add additional context in comments.

2 Comments

That's a nice way to do it -- takes all the fun out of the loop, but a nice way to go.
Thank you for this simpler approach.
3

You are close, but you need to create the directories one-at-a-time and then change into the newly created directory before creating the next. That way with each argument you take you create one-level of directory, e.g.

#!/bin/bash

for i in "$@"; do
    mkdir -p "$i" && cd "$i"
done

(note: by using the compound command joined with &&, you only change to the new directory if mkdir -p succeeds)

Another way to write it would be:

for i in "$@"; do
    mkdir -p "$i"
    if [ -d "$i" ]; then
        cd "$i"
    fi
done

You ALWAYS quote your variables. That way iterating over the arguments if they are:

bash yourscript.sh dir1 "dir1 a" dir2

You will actually create your three directories dir1, dir1 a and dir2. If you FAIL to QUOTE, you would create dir1, dir1, a and dir2 (4-directories)

Example Use/Results

$ bash myscript.sh my dog has fleas

Checking:

$ tree my
my
└── dog
    └── has
        └── fleas

Let me know if you have questions.

1 Comment

This is exactly what I am looking to do as I am practicing for loops. Thank you.
0

a sed way of doing. with sed we are just replacing the spaces with "/" which would do the trick

cat hi.sh
mkdir -p `echo $@|sed -e 's/\ /\//g'`

execute the script with arguments

./hi.sh 1 2 3 4 5

listing the created directories

tree
.
├── 1
│   └── 2
│       └── 3
│           └── 4
│               └── 5
├── hi.env
└── hi.sh

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.