Bash script to copy files from cd to directory - bash

I have no bash scripting knowledge unforunately. I need a script that reads a cd copied ONE file from the cd to a destination and renames it. Here is my code
#!/bin/bash
mount /dev/cd0 /mnt/
for file in /mnt/*
do
if($file == SO_CV*)
cp SO_CV* /usr/castle/np_new/CVFULLPC.BIN
else if($file == SO_PC*)
cp SO_PC* /usr/castle/np_new/PCMAP.BIN
else if($file == MS_PC*)
cp MS_PC* /usr/castle/np_new/FULLPC.BIN
else if($file == MS_MC*)
cp MS_MC* /usr/castle/np_new/MBFULLPC.BIN
done
umount /mnt/
Could someone tell me if this is even valid bash scripting, or what mistakes I might have made.
Thanks
Jim

Syntax problems. Try this code:
#!/bin/bash
mount /dev/cd0 /mnt/
for file in /mnt/*; do
if [[ "$file" == SO_CV* ]]; then
cp SO_CV* /usr/castle/np_new/CVFULLPC.BIN
elif [[ "$file" == SO_PC* ]]; then
cp SO_PC* /usr/castle/np_new/PCMAP.BIN
elif [[ "$file" == MS_PC* ]]; then
cp MS_PC* /usr/castle/np_new/FULLPC.BIN
elif [[ "$file" == MS_MC* ]]; then
cp MS_MC* /usr/castle/np_new/MBFULLPC.BIN
fi
done
umount /mnt/

an alternative:
#!/bin/bash
error_in_cp () {
{ printf "An ERROR occured while trying to copy: '\s' to its dest file.\n" "$#"
printf "Maybe there were more than 1 file ? or you didn't have the rights necessary to write the destination?"
printf "Exiting..."
} >&2 #to have it on STDERR
exit 1
}
mount /dev/cd0 /mnt/ &&
for file in /mnt/*; do
case "$file" in
SO_CV*) cp -p SO_CV* /usr/castle/np_new/CVFULLPC.BIN || error_in_cp "$file" ;;
SO_PC*) cp -p SO_PC* /usr/castle/np_new/PCMAP.BIN || error_in_cp "$file" ;;
MS_PC*) cp -p MS_PC* /usr/castle/np_new/FULLPC.BIN || error_in_cp "$file" ;;
MS_MC*) cp -p MS_MC* /usr/castle/np_new/MBFULLPC.BIN || error_in_cp "$file" ;;
*) echo "oops, forgot to handle that case: '$file' . ABORTING. "
exit 1
;;
esac
done # no "&&" here so you always umount /mnt/ even if you aborted the copy or the latest command went wrong
umount /mnt/
note: I changed the "cp" to "cp -p" to prevere rights & times... adjust if needed.
note that "&&" at the end of the line is ok
(no need to :
command && \
something
)
You may need to add { and } around each part if there is more than 1 element (here, "case ... esac" is one element, so it's fine)

Related

Bash mkdir and cd script returning error but still working

For a while, I've had a need for a bash script to make a directory and cd into it. Most of the solutions online work but are very minimal so I wanted to make one that handles things like creating parent directories and permission checking. Here's my code:
#!/bin/bash
function mkcd() {
# Check for no arguments
if "$#" -eq 0; then
echo "Error: no arguments provided"
return 1
fi
# Checks if help flag is used
# Not with other flags to ensure the directory isn't assumed to be a flag
if [[ "$1" == "-h" || "$1" == "--help" ]]; then
echo "mkcd - Makes a directory and changes directory to it\n"
echo "Flags:"
echo " -h, --help Display help message"
echo " -p, --parents Makes parent directories as neeeded"
echo " -a, --absolute Receive an absolute directory instead of relative\n"
echo "Format: mkcd [arguments] directory"
return 0
fi
# Flag checker
while test "$#" -gt 1; do
case "$1" in
-p | --parents)
mkcd_parents=true
shift
;;
-a | --absolute)
shift
;;
esac
done
mkcd_path="$1"
if [[ ! -w "$PWD" ]]; then
echo "Error: Permission denied"
return 1
fi
if [[ -d "$mkcd_path" ]]; then
echo "Error: Directory already exists"
return 1
fi
if "$mkcd_parents"; then
mkdir -p "$mkcd_path"
cd "$mkcd_path"
else
mkdir "$mkcd_path"
cd "$mkcd_path"
fi
}
I also sourced it in my .zshrc file with source ~/bin/*
When I run the command, I get this output:
~ ❯ mkcd test_dir
mkcd:3: command not found: 1
mkcd:45: permission denied:
~/test_dir ❯
Does anyone understand why I'm getting this error?
if "$#" -eq 0; then
Since you have one argument to the script, that becomes after expansions
if 1 -eq 0; then
You probably meant to do
if [[ "$#" -eq 0 ]]; then
instead. (With either of [ .. ] or [[ .. ]].)
As an aside, I would change this
if "$mkcd_parents"; then
to
if [ "$mkcd_parents" = "true" ]; then
Otherwise if the -p option isn't given, $mkcd_parents is unset, "$mkcd_parents" expands to the empty string, and you get an error about that command not being found.

What am I missing in this simple Bash script?

#!/bin/bash
#Toggle Script
# $dirserver/A -> $dirproject/{trunk|branches}/A
if [[ "$1" == "dw" || -z "$1" ]]; then
echo "[+] Delete old link ( $dirserver/A )... "
rm "$dirserver/A"
if [[ "$(readlink -f $dirserver/A)" == *"branches"* ]]; then
ln -s "$dirproject/trunk/A" "$dirserver/A"
echo "[+] Done. You are now in TRUNK"
else
ln -s "$dirproject/branches/A" "$dirserver/A"
echo "[+] Done. You are now in BRANCH."
fi
fi
Expected functionality: Do toggle between symlinks, BRANCH or TRUNK .
Error: ./toggle.sh dw Always end in BRANCH.
Notes: No. There is no word "branches" when it points to trunk.
Thank you in advance.
You are deleting the old link before checking it. Just do not delete it at all, only overwrite.
if [[ "$1" == "dw" || -z "$1" ]]; then
if [[ "$(readlink -f "$dirserver/A")" == *branches* ]]; then
ln -f -s "$dirproject/trunk/A" "$dirserver/A"
else
ln -f -s "$dirproject/branches/A" "$dirserver/A"
fi
fi

mkdir not working in centos 7?

I have this little bash script that I'm writing to create files in particular directory by reading lines in a file. But the issue is mkdir is not creating dir, not sure why and it is working I try it outside the script. Below is my script...
#!/bin/bash -x
source credentials.sh
OPTARG=""
while getopts :i:x:n name
do
case $name in
x) inputfile="$OPTARG" ;;
i) outputPath="$OPTARGS" ;;
n) dirName="$OPTARG" ;;
esac
done
if [ ! "$dirName" ]
then
mkdir $dirName || echo "error while creating dir"
fi
while read -r line;
do
touch "$line"
mv "$line" "$dirName"
done < $inputfile
ERROR:
[root#Buy]# ./prepare_messages.sh -x file.txt -n testdir
mkdir: missing operand
I searched and tried few but not working, can someone please shed some light...
Thx,
Arun
[ ! "$dirName" ] doesn't test whether the directory exists, it just tests whether the string $dirName is empty or not. You need:
if [ ! -d "$dirName" ]
You should also quote the variable when calling mkdir:
mkdir "$dirName" || echo "error while creating dir"
Your getopts call is wrong. The : character goes after the option that takes the argument. Since you don't have : after n, $OPTARG wasn't being set for that option, so $dirName is always empty. It should be getopts i:x:n: name.
There's also no $OPTARGS variable, that should be $OPTARG.
The full correction:
#!/bin/bash -x
source credentials.sh
OPTARG=""
while getopts i:x:n: name
do
case $name in
x) inputfile="$OPTARG" ;;
i) outputPath="$OPTARG" ;;
n) dirName="$OPTARG" ;;
esac
done
if [ ! -d "$dirName" ]
then
mkdir "$dirName" || echo "error while creating dir"
fi
while read -r line;
do
touch "$line"
mv "$line" "$dirName"
done < "$inputfile"
Got it working, below is corrected line of code. Missing ":" at end of getopts args...
while getopts :i:x:n: name

BASH - Safe check before running "rm -fr $FOLDER"

I have a script which really needs an rm -fr on a specific folder
I'd like to make this as safe as possible. I started this script below but I was wondering if there's anything else I missed.
folder=""
if [[ ! -d "$folder" ]]; then
echo "Error: is not a folder"
elif [[ "$folder" == "/" ]]; then
echo "Error: folder points to root"
elif [[ "$folder" == "../"* ]]; then
echo "Error: folder start with ../"
elif [[ "$folder" == *"/.."* ]]; then
echo "Error: folder contains /.."
elif [[ "$folder" == *"/*"* ]]; then
echo "Error: folder ends with /*"
else
rm -fr "$folder"
fi
Update: added the check for "/"
If you want to be as safe as possible, you could perhaps...
Make sure any globbing is done first :
shopt -s nullglob
declare -a folders=(folder_or_glob)
Iterate over each element of the array, one at a time, and operate on the canonical path.
for f in "${folders[#]-}"
do
[[ $f ]] || continue
candidate="$(realpath -e -s "$f")" || continue
ok_to_delete "$candidate" || continue
rm -rf "$candidate"
done
Use function ok_to_delete to test :
ok_to_delete()
{
[[ -d $1 ]] || continue # Is directory
[[ $1 != / ]] || continue # Not root
[[ "${1%/*}" ]] || continue # At least two levels deep
(... add any test you want ...)
}
There is a bit of redundancy here (e.g. not root + 2 levels deep), but this is just to give you ideas.
Instead of checking the path name of folder, I would rather to check the contents in that folder, file's size/user/timestamp/keywork/extension, etc, or whatever you care most about. This is a more safe method for you, this's just my two cents.

Getting stuck in a logic statement

I'm writing a BASH script to purge the cache from a web server. The script is designed to take arguments from positional parameters. "ShellCheck.net" is telling me that my script is functionally correct, but when I test it I'm getting error where I shouldn't ... so I thought I'd ask for some folks to put fresh eyes on it. Take a look, I'll continue below and describe my problem:
#!/bin/bash
#
# Verify the user running is root, if not, fail.
if [[ "$UID" -ne "0" ]]; #added-1438279711
then
echo 'Only ROOT may run this script.';
exit 1;
fi
#
# Set the variables
BASE="/path/to/folder/foo/bar/" #added-1438279711
DOMAINOPT="$1" #added 1438451428
PATHOPT="$2" #added 1438451428
#
# Define Functions
function usage() { #added-1438382631
echo -en "Proper Usage:\n\n"
echo -en "\tSpecify the domain to be used\n"
echo -en "\tUsage: \"cleancache.sh abc.com\"\n"
echo -en "\t\tNote: This option will search for files and folders, recursively, within the domain folder, and remove them.\n\n"
echo -en "\tSpecify the URI you'd like to act upon within the domain\n"
echo -en "\tUsage: \"cleancache.sh abc.com /path/to/folder/\"\n"
echo -en "\t\tNote: This option will search for files and folders, recursively,\n\t\twithin the specified path, and remove them. Removing a single file is not currently supported with this script.\n\n"
}
#
# Validate the input
if [[ ! -z "$DOMAINOPT" ]] && [[ "$DOMAINOPT" != "^[A-Za-z0-9-]*[\.][a-z]*$" ]] #added-1438462778
then
clear
echo -en "Please follow the proper format for the DOMAIN option\n\n"
usage
exit 1
elif [[ ! -z "$DOMAINOPT" ]] && [[ "$DOMAINOPT" = "^[A-Za-z0-9-]*[\.][a-z]*$" ]]
then
DOMAINOPT="$DOMAINOPT"
else
clear
echo -en "Please enter a domain!\n\n"
usage
exit 1
fi
if [[ ! -z "$PATHOPT" ]] && [[ "$PATHOPT" != "^[\/][\S]*[\/]$" ]] #added-1438456371
then
clear
echo "Please follow the proper format for the PATH option"
usage
exit 1
elif [[ ! -z "$PATHOPT" ]] && [[ "$PATHOPT" = "^[\/][\S]*[\/]$" ]]
then
PATHOPT="$PATHOPT"
else
echo ""
fi
#
# Doing Stuff
if [[ "$#" -gt "2" ]]
then
echo -en "Too many arguments!\n\n"
usage
exit 1
elif [[ "$#" -eq "2" ]]
then
echo "Purging Cache in \"$BASE$DOMAINOPT$PATHOPT\""
find "$BASE""$DOMAINOPT""$PATHOPT" -type d -exec rm -rf {} \;
find "$BASE""$DOMAINOPT""$PATHOPT" -type f -exec rm -f {} \;
echo "Purging Complete"
exit 0
else
echo "Purging Cache in \"$BASE$DOMAINOPT\""
find "$BASE" -type d -name "$DOMAINOPT" -exec rm -rf {} \;
mkdir -p "$BASE$DOMAINOPT" && chown apache:apache "$BASE$DOMAINOPT" && chmod 755 "$BASE$DOMAINOPT"
echo "Purging Complete!"
echo "Creating \".stat\" file"
echo "" > "$BASE""$DOMAINOPT""/.stat"
if [[ -f "$BASE""$DOMAINOPT""/.stat" ]] #added-1438387045
then
echo "$BASE$DOMAINOPT/.stat file created!"
fi
fi
echo "All Operations Complete, exiting now!"
Everything responds normally if you run the script without any arguments (Please enter a domain), It responds normally if you try to enter a path before a domain ... but when I do it correctly, when I type: "cleancache.sh abc.com", I get an error like i haven't met the required pattern ("Please follow the proper format for the DOMAIN option") ... when that is exactly write! ... I don't understand what I'm missing, been banging my head all day, no joy.
PLEASE HELP!
Use this to match a regex:
[[ "$DOMAINOPT" =~ ^[A-Za-z0-9-]*[\.][a-z]*$ ]]
or this:
[[ ! "$DOMAINOPT" =~ ^[A-Za-z0-9-]*[\.][a-z]*$ ]]
Don't quote the regex.

Resources