I have the following script:
#!/bin/bash
path="/parentfolder/{child_1,child_2}"
mkdir -p $path
mkdir -p /parentfolder/{child_3,child_4}
Running it creates the following folders:
/parentfolder/{child_1,child_2}
/parentfolder/child_3
/parentfolder/child_4
How can I make the script create the following folder structure:
/parentfolder/child_1
/parentfolder/child_2
/parentfolder/child_3
/parentfolder/child_4
You cannot use brace expansion in a quoted variable; either put the braces in the command itself, or assign the variable differently. If you need the values to be in a variable, using an array would seem suitable.
#!/bin/bash
paths=(/parentfolder/{child_1,child_2,child_3,child_4})
mkdir -p "${paths[#]}"
path=`echo /parentfolder/{child_1,child_2}`
expansion needs a command to work properly.
Related
I'm trying to create directory using if condition statement, while running script i am not able to find any expected result from the script, but when i am running manually only mkdir command alone its creating as we expected; here the sample code.
#!/bin/bash
dir_path=/tmp/opt/app/software/{A,B,C,D}
if [[ -d $dir_path ]]; then
mkdir -p /tmp/opt/app/software/{A,B,C,D}
fi
can you please advise, how we can create this..
dir_path is a "list" of directory paths due to the {} parameter expansion. If you write this out:
dir_path=/tmp/opt/app/software/A /tmp/opt/app/software/B /tmp/opt/app/software/C /tmp/opt/app/software/D
This is what's being used in the test of the if statement.
Either you want to iterate over the list of sub directories, or just pass them to mkdir. mkdir simply won't create the directory if it already exists.
Your mkdir command actually expands out to:
mkdir -p /tmp/opt/app/software/A /tmp/opt/app/software/B /tmp/opt/app/software/C /tmp/opt/app/software/D
If you want to itterate and still do a check (which while needless in this example can still be useful other times.)
# Declare the variable `dirs` to be an array and use
# parameter expansion to populate it
declare -a dirs=(/tmp/opt/app/software/{A,B,C,D});
# Iterate over the array of directory names
for dir in ${dirs[#]}; do
if [ ! -d "$dir" ]; then
# The directory does not exsist
mkdir -p "$dir"; # Make the directory
fi
done
I have the following typical problem with my workflow: I want to copy some files to a directory that is not yet created. Mostly I do it in this way:
cp *.JPG /some/path/[oops, I recalled that the directory does not exist, ^C]
mkdir /some/path/newdir
cp *.JPG /some/path/newdir
To avoid this I created a script called md that creates a directory and returns its path:
#!/bin/sh
mkdir -p "$*"
echo "$*"
Then my workflow looks like this:
cp *.JPG `md /some/path/newdir`<TAB><ENTER>
When I press <TAB>, md is executed, the directory created and line with backticks substituted with its path, then I can press <ENTER> and execute cp.
Everything works fine unless I have spaces in the path of the new directory. In that case, after expansion, I have unescaped spaces on my command line.
I tried to overcome this by putting the path in quotes like this (in md):
echo "'$*'"
But in this case after expansion I have quotes escaped:
cp *.JPG \'/Users/user/temp/one two three\'
Is there any way to avoid escaping of quotes on command expansion in zsh? I tried $() and different types of quotes (" instead of '), but nothing works.
Of course, I can just do it in this way:
cp *.JPG "`md /path/with spaces`"
But I want to save a couple of keystrokes, if possible.
I think the easiest way to solve that is by creating a script/function for the whole thing (I'd prefer a function, because you're presumably going to be using it only from an interactive shell session):
#Ensures Targetdir exists and then copies into it
#Usage: cp_t Targetdir FlagsAndFiles...
cp_t()
(
targetdir="$1"; shift || return 1
[ -d "$targetdir" ] || mkdir -p "$targetdir" || return 1
exec cp "$#" "targetdir"
)
(This is POSIX too, so you should be able to use it with other POSIX shells as well.)
I am using Cygwin Terminal to run shell to execute shell scripts of my Windows 7 system.
I am creating directory , but it is getting created with a dot in name.
test.sh
#!/bin/bash
echo "Hello World"
temp=$(date '+%d%m%Y')
dirName="Test_$temp"
dirPath=/cygdrive/c/MyFolder/"$dirName"
echo "$dirName"
echo "$dirPath"
mkdir -m 777 $dirPath
on executing sh test.sh its creating folder as Test_26062015 while expectation is Test_26062015.Why are these 3 special charterers coming , how can I correct it
Double quote the $dirPath in the last command and add -p to ignore mkdir failures when the directory already exists: mkdir -m 777 -p "$dirPath". Besides this, take care when combining variables and strings: dirName="Test_${temp}" looks better than dirName="Test_$temp".
Also, use this for static analysis of your scripts.
UPDATE: By analyzing the debug output of sh -x, the issue appeared due to DOS-style line-endings in the OP's script. Converting the file to UNIX format solved the problem.
I want to create multiple subdirectories.
My command is:
mkdir -p dir1/{dir1.1/{dir1.1.1,dir1.1.2},dir1.2,dir1.3}
It works, result is:
dir1
dir1.1
dir1.1.1
dir1.1.2
dir1.2
dir1.3
However I want to make this command look nicer (more readable). Tried to:
mkdir -p \
dir1/{\
dir1.1/{\
dir1.1.1,\
dir1.1.2},\
dir1.2,\
dir1.3}
And this doesn't work. Result is:
ls *
dir1 dir1.1 dir1.1.1, dir1.1.2}, dir1.2, dir1.3}
How can I wrap such mkdir command?
Try the following:
eval mkdir -p `echo \
dir1/{\
dir1.1/{\
dir1.1.1,\
dir1.1.2},\
dir1.2,\
dir1.3}\
| sed -E 's/\s*//g'`
Explanation: Your original code introduces spaces into the parameter, so instead of calling
mkdir -p dir1/{dir1.1/{dir1.1.1,dir1.1.2},dir1.2,dir1.3}
You are actually calling the command with the following parameters:
mkdir -p dir1/{ dir1.1/{ dir1.1.1, dir1.1.2}, dir1.2, dir1.3}
And this is why you got the wrong directories created. Therefore, to solve this, I first stripped the whitespaces using sed, and then used eval to evaluate the resulting command. This solution should work for simple cases, but some special characters within the directory names (such as white spaces) may cause issues.
Hope this helps!
If you want readable, just call mkdir multiple times. I doubt that directory creation is going to form any kind of bottleneck in your program.
mkdir dir1
mkdir -p dir1/dir1.{1,2,3}
mkdir -p dir1/dir1.1/dir1.1.{1,2}
The problem is the whitespace in the beginning of each line, which causes the lines to be treated as different arguments of the mkdir command. To overcome this, you can do:
mkdir -p \
dir1/{\
dir1.1/{\
dir1.1.1,\
dir1.1.2},\
dir1.2,\
dir1.3}
with no whitespace in the beginning. Whether this is more readable than the first command is debatable.
The following is a fragment of a bash script that I'm running under cygwin on Windows:
deployDir=/cygdrive/c/Temp/deploy
timestamp=`date +%Y-%m-%d_%H:%M:%S`
deployDir=${deployDir}/$timestamp
if [ ! -d "$deployDir" ]; then
echo "making dir $deployDir"
mkdir -p $deployDir
fi
This produces output such as:
making dir /cygdrive/c/Temp/deploy/2010-04-30_11:47:58
mkdir: missing operand
Try `mkdir --help' for more information.
However, if I type /cygdrive/c/Temp/deploy/2010-04-30_11:47:58 on the command-line it succeeds, why does the same command not work in the script?
Thanks,
Don
Change:
mkdir -p $deploydir
to
mkdir -p "$deployDir"
Like most Unix shells (maybe even all of them), Bourne (Again) Shell (sh/bash) is case-sensitive. The dir var is called deployDir (mixed-case) everywhere except for the mkdir command, where it is called deploydir (all lowercase). Since deploydir (all lowercase) is a considered distinct variable from deployDir (mixed-case) and deplydir (all lowercase) has never had a value assigned to it, the value of deploydir (all lowercase) is empty string ("").
Without the quotes (mkdir $deploydir), the line effectively becomes mkdir (just the command without the required operand), thus the error mkdir: missing operand.
With the quotes (mkdir "$deploydir"), the line effectively becomes mkdir "" (the command to make a directory with the illegal directory name of empty string), thus the error mkdir: cannot create directory'.
Using the form with quotes (mkdir "$deployDir") is recommended in case the target directory name includes spaces.
Change:
mkdir -p $deploydir
to
mkdir -p "$deploydir"
You can't have colons in file names on Windows, for obvious reasons.