Extract folder names and create directory - bash

I have to extract folder names (folder10 folder44 etc) using for loop and make directory using each folder names but I get file names (file1 file12) and I get an error while creating directory i.e "Directory cannot be created". I have to operate on .txt files in my pipeline so I can't skip /home/data/folder*/file* in for loop
How can I get folder names instead of file names
#!/bin/bash
$out_dir=/home/data/results
for file in /home/data/folder*/file*
do
txtFile=${file##*/}
id=${txtFile%.txt}
echo "mkdir -p $out_dir/"${id}""
done
Folders and File structure
/home/data/folder10/file1/file1.txt
/home/data/folder44/file12/file12.txt
/home/data/folder100/file3/file3.txt
/home/data/folder250/file4/file4.txt
/home/data/folder1245/file5/file5.txt
output which I get
mkdir -p /home/data/results/file1
mkdir -p /home/data/results/file12
mkdir -p /home/data/results/file3
expected output will be
mkdir -p /home/data/results/folder10
mkdir -p /home/data/results/folder44
mkdir -p /home/data/results/folder100

This this:
#!/bin/bash
out_dir=/home/data/results
for file in /home/data/folder*/file*.txt; do
folder=${file%/*}
mkdir -p "$out_dir/${folder##*/}"
done
Or this:
#!/bin/bash
out_dir=/home/data/results
for file in /home/data/folder*/file*/file*.txt; do
folder=${file%/*/*}
mkdir -p "$out_dir/${folder##*/}"
done

Related

Batch create folders from TXT file... with subfolders in them

I have a TXT file with 1,000 lines of product numbers I need to make into 1,000 folders with two subfolders in each named IMAGE & SPEC. I want to run it in Automator or from Terminal on my mac but cannot find the answer ANYWHERE! Any help out there?
In Terminal.app, type “cd “ (without the quotes but make sure there is a space after cd). Then drag the folder from Finder (the folder where you want the 1000 new folders created in) Into Terminal.app. This will change the working directory to the directory to where the new folders will be created.
If your products.txt file is located in the same directory as the 1000 new folders will be created, enter this following line of code into the Terminal window and be sure to change the name “products.txt” to your actual file name.
while read line; do mkdir -p "$line/IMAGE"; mkdir -p "$line/SPEC"; done < products.txt
If your products.txt file is located elsewhere, then use this line of code instead.
while read line; do mkdir -p "$line/IMAGE"; mkdir -p "$line/SPEC"; done <
then drag the “products.txt” file from Finder Into Terminal.app. Then it should look something like this (assuming the “products.txt” file was on you Desktop)
while read line; do mkdir -p "$line/IMAGE"; mkdir -p "$line/SPEC"; done < /Users/YourShortName/Desktop/products.txt
you can use pure shellscript for this task like below:
while read line;
do
mkdir -p "$line/IMAGE";
mkdir -p "$line/SPEC";
done < products.txt

Trying to write a MacOS automator script to make incrementing folders based off of scanned input

New to bash scripting, and I'm stuck. Within a static directory I'm trying to create a folder '001_scanned name' and within that directory create 6 more subfolders. I'm able to do it all brutishly with this code:
cd ~/deej/Test/Capture
mkdir "$1"
cd "$1"
mkdir "$1_1"
mkdir "$1_2"
mkdir "$1_3"
mkdir "$1_4"
mkdir "$1_5"
mkdir "$1_6"
Ugly, but works for now.
$1 is the scanned name and I was manually appending the prefix of the file names with "001, 002, etc.". Is there an easy way to do this within an Automator prompt since I'll be unable to keep the last variable stored in the code?
If you use the -p option with mkdir it will create intermediate directories as needed so you can do both commands at once. The seq function can create zero-padded integers:
for n in $(seq -f "%03g" 1 10);
do mkdir -p ${i}/${i}_${n};
done;
You can test using echo instead of mkdir -p. Below I had i set to 015...
015/015_001
015/015_002
015/015_003
015/015_004
015/015_005
015/015_006
015/015_007
015/015_008
015/015_009
015/015_010

is there any single command to create a file with missing directory structure

Is there any single command to create a file with missing directory structure?
Suppose I have a variable LOG_STORAGE_PATH=/var/log/app-log/access.log in my shell script and I dont know if app-log directory and access.log file is present.
Is there a single command, like mkdir -p </some/random/path> which creates all intermediate directories if not present, to create a file with missing directories in between.
This would have been accomplished with the help of
LOG_STORAGE_PATH=/var/log/app-log/
ACCESS_LOG_FILE=access.log
ACCESS_LOG_FILE_PATH=${LOG_STORAGE_PATH}/${ACCESS_LOG_FILE}
if [ ! -d ${LOG_STORAGE_PATH} ]
then
mkdir -p ${LOG_STORAGE_PATH}
fi
if [ ! -f ${ACCESS_LOG_FILE_PATH} ]
then
touch ${ACCESS_LOG_FILE_PATH}
fi
I was looking for touch command with same functionality as mkdir -p, but its not present.
It would have been very useful if we had a touch -p /var/log/app-log/access.log command which can create a file along with missing directories, or if directories are present then just create the file or even if directories and file both present then just update the access time of the file.
Just for a thought, maybe we wouldn't have to use if [ ! -f <some file> ] or if [ ! -d <some dir path> ] in our scripts, we could have directly used touch -p ${ACCESS_LOG_FILE_PATH}
You cannot able to do this with single command in unix. To do this you need two commands (mkdir and touch).

How to create subfolders and files if not present inside a script without multiple mkdir?

What is a better way to create sub folders in a shell script? Instead of using the following method?
mkdir /var/log
mkdir /var/log/celery
mkdir /var/log/celery/stdout
mkdir /var/log/celery/stderr
touch /var/log/celery/stdout/stdout.log <<< I'm hoping the use this path create folder if doesn't exists....
touch /var/log/celery/stderr/stderr.log
mkdir has a -p flag that will create parent directories but touch will not create directories that do not exist.
That still cuts the above down to:
mkdir -p /var/log/celery/stdout /var/log/celery/stderr
touch /var/log/celery/stdout/stdout.log /var/log/celery/stderr/stderr.log
Which in a shell that supports brace expansion could even be:
mkdir -p /var/log/celery/{stdout,stderr}
touch /var/log/celery/{stdout/stdout.log,stderr/stderr.log}
And actually, if you have brace expansion but not mkdir -p you could do:
mkdir /var/log{,/celery{,/{stdout,stderr}}}
touch /var/log/celery/{stdout/stdout.log,stderr/stderr.log}
But there isn't any way to combine the mkdir and touch steps with standard tools that I'm aware of.
The -p option of mkdir will create the intermediate folders of the path if they don't exists (and of course, if you have the appropriate privileges):
mkdir -p /var/log/celery/stderr
To create the file, you can append the touch after the operator &&, so the touch operation only occurs if the directory either was created successfully or already exists:
mkdir -p /var/log/celery/stderr && touch "$_/stderr.log"
(Basically, the $_ will pass the dir path to the touch command)
UNTESTED:
$ needir () { mkdir -p $1; echo $1; }
$ touch $(needir /var/log/celery/stderr)/stderr.log
and put "needir" in your .profile, or better yet, in a function library on your path that you source when you login. you'd be surprised how often you'll be using it.

How to mkdir only if a directory does not already exist?

I am writing a shell script to run under the KornShell (ksh) on AIX. I would like to use the mkdir command to create a directory. But the directory may already exist, in which case I do not want to do anything. So I want to either test to see that the directory does not exist, or suppress the "File exists" error that mkdir throws when it tries to create an existing directory.
How can I best do this?
Try mkdir -p:
mkdir -p foo
Note that this will also create any intermediate directories that don't exist; for instance,
mkdir -p foo/bar/baz
will create directories foo, foo/bar, and foo/bar/baz if they don't exist.
Some implementation like GNU mkdir include mkdir --parents as a more readable alias, but this is not specified in POSIX/Single Unix Specification and not available on many common platforms like macOS, various BSDs, and various commercial Unixes, so it should be avoided.
If you want an error when parent directories don't exist, and want to create the directory if it doesn't exist, then you can test for the existence of the directory first:
[ -d foo ] || mkdir foo
This should work:
$ mkdir -p dir
or:
if [[ ! -e $dir ]]; then
mkdir $dir
elif [[ ! -d $dir ]]; then
echo "$dir already exists but is not a directory" 1>&2
fi
which will create the directory if it doesn't exist, but warn you if the name of the directory you're trying to create is already in use by something other than a directory.
Use the -p flag.
man mkdir
mkdir -p foo
Defining complex directory trees with one command
mkdir -p project/{lib/ext,bin,src,doc/{html,info,pdf},demo/stat/a}
If you don't want to show any error message:
[ -d newdir ] || mkdir newdir
If you want to show your own error message:
[ -d newdir ] && echo "Directory Exists" || mkdir newdir
mkdir foo works even if the directory exists.
To make it work only if the directory named "foo" does not exist, try using the -p flag.
Example:
mkdir -p foo
This will create the directory named "foo" only if it does not exist. :)
The old tried and true
mkdir /tmp/qq >/dev/null 2>&1
will do what you want with none of the race conditions many of the other solutions have.
Sometimes the simplest (and ugliest) solutions are the best.
Simple, silent and deadly:
mkdir -p /my/new/dir >/dev/null 2>&1
You can either use an if statement to check if the directory exists or not. If it does not exits, then create the directory.
dir=/home/dir_name
if [ ! -d $dir ]
then
mkdir $dir
else
echo "Directory exists"
fi
You can directory use mkdir with -p option to create a directory. It will check if the directory is not available it will.
mkdir -p $dir
mkdir -p also allows to create the tree structure of the directory. If you want to create the parent and child directories using same command, can opt mkdir -p
mkdir -p /home/parent_dir /home/parent_dir/child1 /home/parent_dir/child2
mkdir does not support -p switch anymore on Windows 8+ systems.
You can use this:
IF NOT EXIST dir_name MKDIR dir_name
directory_name = "foo"
if [ -d $directory_name ]
then
echo "Directory already exists"
else
mkdir $directory_name
fi
This is a simple function (Bash shell) which lets you create a directory if it doesn't exist.
#------------------------------------------#
# Create a directory if it does not exist. #
#------------------------------------------#
# Note the "-p" option in the mkdir #
# command which creates directories #
# recursively. #
#------------------------------------------#
createDirectory() {
mkdir -p -- "$1"
}
You can call the above function as:
createDirectory "$(mktemp -d dir-example.XXXXX)/fooDir/BarDir"
The above creates fooDir and BarDir if they don't exist. Note the "-p" option in the mkdir command which creates directories recursively.
Referring to man page man mkdir for option -p
-p, --parents
no error if existing, make parent directories as needed
which will create all directories in a given path, if exists throws no error otherwise it creates all directories from left to right in the given path. Try the below command. the directories newdir and anotherdir doesn't exists before issuing this command
Correct Usage
mkdir -p /tmp/newdir/anotherdir
After executing the command you can see newdir and anotherdir created under /tmp. You can issue this command as many times you want, the command always have exit(0). Due to this reason most people use this command in shell scripts before using those actual paths.
Or if you want to check for existence first:
if [[ ! -e /path/to/newdir ]]; then
mkdir /path/to/newdir
fi
-e is the exist test for KornShell.
You can also try googling a KornShell manual.
Improvement on the 'classic' solution (by Brian Campbell) - to handle the case of symlink to a directory.
[ -d foo/. ] || mkdir foo
mkdir -p sam
mkdir = Make Directory
-p = --parents
(no error if existing, make parent directories as needed)
if [ !-d $dirName ];then
if ! mkdir $dirName; then # Shorter version. Shell will complain if you put braces here though
echo "Can't make dir: $dirName"
fi
fi

Resources