Prevent mkdir -p from overwriting directories and cp from overwriting files - linux

I have a shell script and I want to use it for making directories and files in those direcctories. It is extremely important that this script does not overwrite or delete any files or directories. So I want to make a directory which is one directory above from the directory where the script is in. In this directory I want to make two subdirectories and in one of the subdirectories I want to copy 2 pre-existing files that have some text in them.
Files file1 and file2 are always going to be in same directory as this script and they always have same contents in them and it is very important that the contents do not change. I have multiple structures like this, they just have different names.
So I tried this:
#! /bin/bash
echo "Enter directory name"
read dirname
mkdir -p ../$dirname/{dir1,dir2}
cp file1 file2 ../$dirname/dir2
But if dirname already exists, this script overwrites it and also overwrites all the contents in it. Then I tried this:
#! /bin/bash
echo "Enter directory name"
read dirname
if [ -d $dirname ]
then
echo "directory already exists"
else
mkdir -p ../$dirname/{dir1,dir2}
cp file1 file2 ../$dirname/dir2
fi
But also this script overwrites everything. How can I make this script so that if dirname already exists, the script does not create new directories and it does not copy any files in any directory, i.e. it does not do anything?

Related

Copy a directory structure and only touch the copied files

I want to mimic copying a directory structure recursively (as in cp -r or rsync -a), but only touch the copied files, i.e. make all the copied files empty.
The specific use case is for a Snakemake pipeline; Snakemake looks for existing files in order to decide whether to re-run a pipeline step, and I want to make it believe the steps have already been run while avoiding fully downloading all the files.
This is a little kludgy, but you could pipe the output of find or rsync -nv into a little bash loop with mkdir -p and touch:
find /some/dir -type f | while read FILE; do
mkdir -p $(dirname $FILE)
touch $FILE
done

How to create a directory and copy files into it with bash

I have some files in Pictures\ with extension *.png and directories like 12-21-20, 12-20-20. These directories was created with dir=mkdir $(date +'%m'-'%d'-'%Y')
At the end of the day I want to run a script which will create a folder $dir and copy all png files I've made for today into that folder. How can I do that? Any information you could give me would be greatly appreciated.
date +'%m-%d-%Y' is the date command outputting, e,g. 12-22-2020. $(..) is called command substitution that captures the result of the date command allowing it to be assigned to the variable dir.
To create a directory with the contents of $dir (e.g. 12-22-2020) you would use the mkdir command, providing the -p option to suppress the error if that directory already exists (and also create parent directories as necessary -- not relevant here). You want to ensure it succeeds before you attempt to copy files to the new directory, so you would use:
mkdir -p "$dir" || exit 1
Which simply exits if the command fails.
At this point, you can simply use cp (or preferably mv to move the files) from whatever source directory they currently reside in. That you can do with:
mv /path/to/source/dir/*.png "$dir"
Or the copy command,
cp -a /path/to/source/dir/*.png "$dir"
Both cp -a and mv will preserve the original file attributes (time, date, permissions, etc...).
From a script standpoint, you will either want to change to the directory above the new "$dir" or use the full path, e.g.
mv /path/to/source/dir/*.png "/path/to/$dir"
Short Example
If you want to provide the directory containing the .png files to move to "$dir" created with today's date, you could write a short script like the following. You provide the directory containing the .png files you would like to copy or move as the first argument to the script on the command-line, e.g. usage would be bash pngscript.sh /path/to/source/dir.
#!/bin/bash
[ -z "$1" ] && { ## validate one argument given for source directory
printf "usage: ./%s /path/to/images" "${0##*/}" >&2
exit 1
}
[ "$(ls -1 "$1"/*.png | wc -l)" -gt 0 ] || { ## validate png files in source dir
printf "error: no .png files in '%s'\n" "$1" >&2
exit 1
}
dir=$(date +'%m-%d-%Y') ## get current date
mkdir -p "$dir" || exit 1 ## create directory, exit on failure
mv "$1"/*.png "$dir" ## move .png files from source to "$dir"
(note: it will create the "$dir" directory below the current working directory and then move files from the path provided as the first argument (positional parameter) to the newly created directory. Change mv to cp -a if you want to leave a copy of the files in the original directory)
You can make the script executable with chmod +x pngscript.sh and then you can simply run it from the current directory as:
./pngscript.sh /path/to/source/dir
Let me know if you have further questions.

Copy files from multiple folders with including folder name in Linux

I have multiple sub folders e.g.:
ls ./
F1 F2 F5 F8 F12 ...
Each folder contain file "file.txt"
How to copy all file.txt files to main folder containing folder name?
cp ./F1/file.txt ./file_1.txt
cp ./F2/file.txt ./file_2.txt
...
Perl One Liner
first go to main folder than:
find . | perl -a -F/ -lne 'qx(cp -r "$F[1]" T/ )'
note
do not worry about log file on the screen if would be!
T/
is your target directory
main folder
Where all your file exist. If your all file is in the folder Music for example; so cd Music then that Perl One Liner
declare -a dirs
i=1
for d in */
do
dirs[i++]="${d%/}"
done
echo "There are ${#dirs[#]} dirs in the current path"
for((i=1;i<=${#dirs[#]};i++))
do
echo "Copying file.txt from ${dirs[i]} dir..."
cp ./${dirs[i]}/file.txt ./file_$i.txt
done
Save it as a script file, fileTxtCopy.sh, for instance. Then place it at the parent dir and give it executable permission sudo chmod +x fileTxtCopy.sh.
Run it as script and you should have all your file.txt file copied in parent dir.
Copies file.txt files from each folder inside a current directory to the current directory and appends numbers contained in a folder name to the name of the copied file.
for i in *; do a=$(<<< "$i" grep -o "[0-9]*" -); cp "$i/file.txt" "file_$a.txt"; done
Not the most robust approach though.

Shell Script: Copy directory passed as variable to another directory also as variable passed by user

SHELL SCRIPT:
How can i copy a directory passed as a variable by user to another directory also as variable?
I mean, the user type a source directory and the destination. So, the files into directory are copied to the other directory.
if cp -R "$source" "$destination"
then echo "Copy successful :)"
else echo "Copy failed :("
fi
The -R option to cp specifies that it should copy the directory recursively. $source should contain the original directory, and $destination should contain the location where you want it copied.
If you want to do something like this:
$ ./script.sh file1.ext file2.ext
The script.sh could be:
#!/bin/bash
cp -rv "$0" "$1"
Hope it helps.

how to write shell script to copy files in the same directory where the script is present

I am running a shell script say xyz.sh. This shell script need to copy all files present in the same directory where this script is present to some another folder. Is there any way to do that?
TARGETDIR='z';for file in *;do test "$file" != "$TARGETDIR" && cp -r "$file" "$TARGETDIR/";done
You should determine dir, where script is placed if you run it not from it's own dir. So, it will looks like:
cp `dirname $0`/* /path/to/newdir/
Now if you call script, dirname $0 will give you base path of where script is placed and cp will copy everything from this path to new location.

Resources