Trying to pass the output of echo into mkdir command - terminal

I know that echo command prints all it's arguments and it does not reads from stdin.
But when I am trying to make echo NAME | mkdir it tells me: mkdir: missing operand.
I tried to read from man mkdir, but it does not tells me where mkdir reads from.

You're passing the name as input, mkdir expects an argument
Try:
echo NAME | xargs mkdir
xargs here provides exactly the missing link: it takes the input stream, and passes it to the program (mkdir, in this case) as arguments.
Note that this parses whitespace-separated elements as different args, so use this with care.
For more information just look at man xargs

mkdir does not read from anywhere; it takes arguments, e.g.
mkdir NAME

Related

Questions about bash

Firstly, I'm wondering how to input information from the terminal into a variable in the script file. For example, lets say I wanted to do ./name.sh dave in the terminal instead of using read -p to ask for the name in the script. Secondly, I'm wondering how to go about creating a new directory and then copying files into that directory. I know how to use the mkdir command, but not how to copy files to that new directory.
Sorry if my wording is a bit bad I wasn't sure how else to ask the questions (this is my first day messing with bash.)
When you run:
./name.sh dave
the string dave will be the first positional argument in the script. You can access it with $1. To create a directory named dave and copy files into it, you might do:
#!/bin/bash
dir=${1:?}
mkdir "$dir" || exit
cp * "$dir"
A few things are a bit cryptic, and perhaps you might prefer:
#!/bin/sh
if test -z "$1"; then
echo "Parameter missing" >&2;
exit 1
fi
mkdir "$1" && cp * "$1"
Basically, you access the parameters via $1, $2, etc. The ${1:?} syntax is a shortcut that assigns the variable dir, but aborts the script if $1 is unset or empty. (eg, if you call the script without an argument.)
The rest seems pretty self-explanatory.
Suppose you wanted to specify the files to copy, so that ./name.sh dave would create a directory named dave and copy all files in the current directory to it (as above), but if you pass more arguments it would copy only those files. In that case, you might do something like:
#!/bin/bash
dir=${1:?}
shift # Discard the first argument, shift remaining down
mkdir "$dir" || exit
case $# in
0) cp * "$dir";;
*) cp "$#" "$dir";;
esac
Here, "$#" is the list of each argument, individually quoted. (eg, if you call the script with an argument that has spaces, it will properly pass that argument to cp. Compare that with cp $# $dir or cp "$*" $dir.) If you're just starting with shell scripts, I would advise you always be careful about quotes.

How to move files if directory is not empty?

I am trying to move files from a directory if it is not empty. This script is added in cronjob but it is always executing regardless of files are present or not? What is wrong in this thing?
#!/bin/bash
logFolder="/dstDir/`date '+%Y-%m-%d/%H-%M'`"
tempLogFolder="sourceDir"
if [ -z "$(ls -A $tempLogFolder | grep *.log)" ]; then
mkdir -p $logFolder
mv $tempLogFolder/*.log $logFolder/
fi
Don't parse the output of ls. You don't need any external commands to count files in a directory. The shell can do it itself.
Try creating a helper function that checks how many arguments are passed to it. Then have the shell expand the glob "$tempLogFolder"/*.log. No need for ls or grep. The only trick is enabling the nullglob option so if no files exist the glob expands to nothing.
files_exist() { (($# > 0)); }
shopt -s nullglob
if files_exist "$tempLogFolder"/*.log; then
mkdir -p "$logFolder"
mv "$tempLogFolder"/*.log "$logFolder"/
fi
grep accepts regex, not glob. If you want to use glob like *.log you put it in your ls something like ls .... *.log (using ls output is not 100% safe).
If you want to use grep, please use regex, I guess what you meant is \.log$.
If you want to check if grep has found matches, you should check the return code ($?) of grep, instead of using -z test.
If you put it in crontab, the script will always be executed.
I think you want,
if [ -n "$(ls -A $tempLogFolder | grep *.log)" ]; then
...
because you are only interested in whether the string returned has a non-zero length.

How to wrap multiple subdirectories mkdir command

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.

bash use second argument of previous command

how I can use the second argument of previous command in a new command ?
example, with
$ mkdir test
I make a directory, how I can use the name of directory for change to this ?
$ mkdir test && cd use_var
$_ is the last (right-most) argument of the previous command.
mkdir gash && cd "$_"
(I don't create files or directories called test, that's the name of a shell built-in and can cause confusions)
With history expansion, you can refer to arbitrary words in the current command line
mkdir dir1 && cd "!#:1"
# 0 1 2 3 4
!# refers to the line typed so far, and :1 refers to word number one (with mkdir starting at 0).
If you use this in a script (i.e., a non-interactive shell), you need to turn history expansion on with set -H and set -o history.
Pressing Esc + . places the last argument of previous command on the current place of cursor. Tested in bash shell and ksh shell.
I use functions for this. Type this in your shell:
mkcd() { mkdir "$1" ; cd "$1" ; }
Now you have a new command mkcd.
If you need this repeatedly, put the line into the file ~/.bash_aliases (if you use bash; other shells use different names).

Shell script on passing arguments

My code was like this I'm passing 4 arguments to a script
ex.sh "wavpath" "featpath"
"ex.sh"
code is
#!/bin/bash
wavPath=$1
featPath=$2
rm -f $scpFile
echo $wavPath
echo $featPath
for dir in `ls -R $wavPath|grep ":"|cut -d':' -f1`
do
mkdir -p ${dir/$wavPath/$featPath}
done
The error message:
bad substitution
and it is at ${dir/$wavPath/$featPath}
and its showing both the paths
can anyone help
Try ${dir}/${wavPath}/${featPath}
maybe you meant $dir/$wavPath/$featPath
try changing
mkdir -p ${dir/$wavPath/$featPath}
to
echo $dir/$wavPath/$featPath
and see if the output is what you expected for the input of mkdir.
Also, you're not setting a value for the variable $scpFile before you use it.

Resources