Giving a parameter and help section to shell script - shell

I have a problem that I want to determine folder name manually. For example, if user runs this script as below,
./scriptname -k
They can take the results, but folder names are determined in script. How can I determine folder name manually as below?

You could write the help as a function:
usage(){
cat <<EOT
Usage: ${0##*/} dir1 dir2
EOT
}
if [ $# -ne 2 ]; then
usage
echo 'please enter two folder names'
exit 1
fi
if [ ! -d "$1" ]; then
usage
echo "$1 is not a folder"
exit 1
fi
if [ ! -d "$2" ]; then
usage
echo "$2 is not a folder"
exit 1
fi
# continue script

#!/bin/bash
check_input_directories()
{
if [[ ! -f "${folder1}" "${folder2}" ]]; then
#your searching program
fi
}
Show_help()
{
cat <<_EOF
Usage : $0 <options> <path>
Options:
-f <folder> <folder>
_EOF
}
MAIN () {
case "$1" in
-f)
check_input_directories
;;
*)
Show_help
esac
}
MAIN $*

I deleted one untested answer yesterday and return today with this tested bash script:
#!/bin/bash
check_input_directories() {
folder1="$1"
folder2="$2"
if [[ ! -d "${folder1}" && ! -d "${folder2}" ]]; then
dir1=~/${folder1}
dir2=~/${folder2}
for i in $(find $dir1 -printf "%f\n")
do
find $dir2 -name $i -print
done
fi
}
Show_help() {
cat <<_EOF
Usage : $0 <options> <path>
You can use this script as below,
-d folder1/ folder2/
_EOF
}
MAIN () {
case "$1" in
-d)
check_input_directories $2 $3
;;
*)
Show_help
esac
}
MAIN $*

Related

Recursively search for files

I am trying to find all files by passing a directory name in all sub directories meaning the process is recursive here is my code
myrecursive() {
if [ -f $1 ]; then
echo $1
elif [ -d $1 ]; then
for i in $(ls $1); do
if [ -f $1 ]; then
echo $i
else
myrecursive $i
fi
done
else
echo " sorry"
fi
}
myrecursive $1
However when I pass directory with another directory I get 2 times sorry,where is my mistake?
The goal that you are trying to achieve could be simply done by using find command:
# will search for all files recursively in current directory
find . * -exec echo {} \;
# will search for all *.txt file recursively in current directory
find . -name "*.txt" -exec echo {} \;
# will search for all *.txt file recursively in current directory
# but depth is limited to 3
find . -name "*.txt" -max-depth 3 -exec echo {} \;
See man find for manual. How to run find -exec?
The problem with your code is quite simple.
The ls command will return a list of filenames, but they aren't valid for
recursion. Use globbing instead. The loop below simply replaces $(ls) with $1/*
myrecursive() {
if [ -f $1 ]; then
echo $1
elif [ -d $1 ]; then
for i in $1/*; do
if [ -f $1 ]; then
echo $i
else
myrecursive $i
fi
done
else
echo " sorry"
fi
}
myrecursive $1
Hope that helps
#!/bin/bash
myrecursive() {
if [ -f "$1" ]; then
echo "$1"
elif [ -d "$1" ]; then
for i in "$1"/*; do
if [ -f "$i" ]; then #here now our file is $i
echo "$i"
else
myrecursive "$i"
fi
done
else
echo " sorry"
fi
}
myrecursive "$1"

Bash script "Syntax Error: Unexpected end of file"

The goal is to create a simple trash utility using a Bourne shell (it's part of an assignment). I am receiving the following error: "line 17: Syntax Error: Unexpected end of file"
I have been staring at the code for a few hours now and I can't see the mistake (probably something simple I am overlooking)
#!/bin/sh
if [$# == 0] ;then
echo "Usage: trash -l | -p | { filename }*"
else
if $1 == '-l'; then
dir $HOME/.trash
else if $1=='-p'; then
rm $HOME/.trash/*
else
for i in ${} ;do
mv i $HOME/.trash
done
fi
fi
Thanks!
This is what I achieved using shellcheck:
#!/bin/sh
if [ $# -eq 0 ] ;then
echo "Usage: trash -l | -p | { filename }*"
else
if [ "$1" = '-l' ]; then
dir "$HOME"/.trash
elif "$1"=='-p'; then
rm "$HOME"/.trash/*
else
for i in ${} ;do
mv "$i" "$HOME"/.trash
done
fi

Need help in resolving a small error in unix shell scripting

I am having a problem with a unix shell script.
The script is for renaming the Files and directories which is having spaces with "-" recursively.
Example "Stack Overflow" to "Stack-Overflow"
This is running perfectly and working , But I get this wierd error which I don't know where it is coming.
I am getting the below error though (last line),
./script.sh[164]: [: Test.dat: unexpected operator/operand
I know it is coming some where in below funtions,
fix_dirs
fix_files
my_rename
but not sure where.
Could some one please help me in finding the error (Sorry for the long script :) )?.
#!/usr/bin/ksh
USAGE="$0 -f directory
$0 -d directory
$0 -d -f directory
-f rename files
-d rename directories
"
usage ()
{
print -u2 "$USAGE"
exit 1
}
pathname ()
{
print -- "${1%/*}"
}
basename ()
{
print -- "${1##*/}"
}
find_dirs ()
{
find "$1" -depth -type d -name '* *' -print
}
find_files ()
{
find "$1" -depth -type f -name '* *' -print
}
my_rename()
{
FROM_DIR="$1";
TO_DIR="$2";
if [ ! -w ${FROM_DIR##*/} ]
then
echo "Directory/file ${FROM_DIR##*/} Not Writable";
exit 1
fi
if [ -d "$TO_DIR" -o -f "TO_DIR" ]
then
echo "Target File or Directory already exists - $TO_DIR ";
exit 1
fi
mv "$FROM_DIR" "$TO_DIR"
STATUS=$?
if [ $STATUS -ne 0 ]
then
echo "Error in moving the file or directory";
echo "From directory : $FROM_DIR";
echo "To directory : $TO_DIR";
fi
}
fix_dirs ()
{
find_dirs "$1"|while read old_directory ; do
is_root_directory=`echo "old_directory" | grep -c "/"`;
if [[ $is_root_directory -ne 0 ]]
then
new_directory=$(pathname "$old_directory")/$(basename "$old_directory" | tr " " "_")
else
new_directory=$(echo "$old_directory" | tr " " "-")
fi
my_rename "${old_directory}" "${new_directory}"
done
}
fix_files ()
{
find_files "$1"|while read old_file ; do
new_file=$(pathname "$old_file")/$(basename "$old_file" | tr " " "-")
my_rename "${old_file}" "${new_file}"
done
}
WFILE=
WDIR=
DIR=
if [ "$#" -eq 0 ]
then
usage
fi
while [ $# -gt 0 ]
do
case $1 in
-d)
WDIR=1
;;
-f)
WFILE=1
;;
-*)
usage
;;
*)
if [ -d "$1" ]
then
DIR="$1"
else
print -u2 "$1 does not exist ..."
exit 1
fi
;;
esac
shift
done
if [ -z "$DIR" ]
then
echo "Please enter the directory";
exit 1
fi
if [ ${PWD} == "$DIR" ]
then
echo "Cannot perform rename on current directory";
exit 1
fi
if [ "$DIR" == "." -o "$DIR" == ".." ]
then
echo "cannot rename current or previous directory";
exit 1
fi
if [[ "$WDIR" == "" && "$WFILE" == "" ]] ; then
usage
exit 1
fi
if [ "$WDIR" -a "$WFILE" ]
then
fix_files "$DIR"
fix_dirs "$DIR"
elif [ "$WDIR" ]
then
fix_dirs "$DIR"
elif [ "$WFILE" ]
then
fix_files "$DIR"
fi
Running "ksh -n" on your example shows some possible problem on lines 70/71:
foo: warning: line 70: `...` obsolete, use $(...)
foo: warning: line 71: -ne within [[...]] obsolete, use ((...))
The relevant lines are
is_root_directory=`echo "old_directory" | grep -c "/"`;
if [[ $is_root_directory -ne 0 ]]
That was using a ksh93 on my Debian6, which likely is not the same version as the one you are using. However, you may find that making the suggested change to the second line will make your warning go away.
Thanks a lot for you information.
I tried bash similar to the ksh.
bash ./scriptname.sh
I corrected the errors. and below are the modified codes,
my_rename()
{
FROM_DIR="$1";
TO_DIR="$2";
if [ ! -w "${FROM_DIR##*/}" ]
then
echo "Directory/file ${FROM_DIR##*/} Not Writable";
exit 1
fi
if [ -d "$TO_DIR" -o -f "TO_DIR" ]
then
echo "Target File or Directory already exists - $TO_DIR ";
exit 1
fi
mv "$FROM_DIR" "$TO_DIR"
STATUS=$?
if [ $STATUS -ne 0 ]
then
echo "Error in moving the file or directory";
echo "From directory : $FROM_DIR";
echo "To directory : $TO_DIR";
fi
}
fix_dirs ()
{
find_dirs "$1"|while read old_directory ; do
is_root_directory=$(echo "$old_directory" | grep -c "/");
if [ $is_root_directory -ne 0 ]; then
new_directory=$(pathname "$old_directory")/$(basename "$old_directory" | tr " " "_")
else
new_directory=$(echo "$old_directory" | tr " " "-")
fi
my_rename "${old_directory}" "${new_directory}"
done
}

Bash script: Copies image files from source dir to destination dir and adds an extra suffix on files with same file name

I have this script that copies image files from source directory to destination directory. There are some image files in the source directory that have the same name but different file size. This script also compares the two files with the same name using a stat command. Now, I want to add a string suffix e.g. IMG0897.DUP.JPG before the file extension to the files with the same file name that are going to be copied over to the destination folder. At the moment, my script adds the file size of the file to the file name.
I need help on how to add a string of text of my own rather than the size of the file.
Here's my script:
#!/bin/sh
SEARCH="IMG_*.JPG"
SOURCE= $1
DEST=$2
test $# -ne 2 && echo Usage : phar image_path archive_path
if [ ! -e $1 ]
then echo Source folder does not exist
fi
if [ ! -e $2 ]
then mkdir $2/
fi
# Execute the script.
if [ "${SEARCH%% *}" = "$SEARCH" ]; then
command="find \"$1\" -name \"$SEARCH\""
else
command="find \"$1\" -name \"${SEARCH%% *}\""$(for i in ${SEARCH#* }; do echo -n " -o -name \"$i\""; done)
fi
# Run the main loop.
eval "$command" | while read file; do
bn=$(basename "$file")
bc=$(stat -c%s "$file")
if [ -f "${2}/$bn" ] && [ "$bc" -ne $(stat -c%s "${2}/$bn") ]; then
bn="$bn.$bc"
fi
if [ -f "${2}/$bn" ]; then
echo "File ${2}/$bn already exists."
else
echo "Copying $file to $2/$bn"
cp -a "$file" "$2/$bn"
fi
done
exit 0
else
echo "Error : Can't find $1 or $2"
exit 1
fi
I modified your scripte slightly.
#!/bin/sh
SEARCH="IMG_*.JPG"
SOURCE=$1
DEST=$2
SUFFIX=DUP
test $# -ne 2 && echo Usage : phar image_path archive_path
if [ ! -e $1 ]
then echo Source folder does not exist
fi
if [ ! -e $2 ]
then mkdir $2/
fi
# Execute the script.
if [ "${SEARCH%% *}" = "$SEARCH" ]; then
command="find \"$1\" -name \"$SEARCH\""
else
command="find \"$1\" -name \"${SEARCH%% *}\""$(for i in ${SEARCH#* }; do echo -n " -o -name \"$i\""; done)
fi
# Run the main loop.
eval "$command" | while read file; do
bn=$(basename "$file")
bc=$(stat -c%s "$file")
if [ -f "${2}/$bn" ] && [ "$bc" -ne $(stat -c%s "${2}/$bn") ]; then
bc=$(echo ${bn}|cut -d. -f2)
bn=$(echo ${bn}|cut -d. -f1)
bn=$bn.$SUFFIX.$bc**
fi
if [ -f "${2}/$bn" ]; then
echo "File ${2}/$bn already exists."
else
echo "Copying $file to $2/$bn"
cp -a "$file" "$2/$bn"
fi
done
exit 0
else
echo "Error : Can't find $1 or $2"
exit 1
fi
My execution result is:
root#precise32:/vagrant# sh JPG_moves.sh /root/dir1/ /root/destination/
Copying /root/dir1/IMG_0897.JPG to /root/destination//IMG_0897.JPG
root#precise32:/vagrant# sh JPG_moves.sh /root/dir2/ /root/destination/
Copying /root/dir2/IMG_0897.JPG to /root/destination//IMG_0897.DUP.JPG

how to be sure that two directories are not subdirectories to each other (BASH)

EDITED: this is more or less what I came up after #Mechanical's nice input. Any insight?
#!/bin/bash
path1="$(readlink -e "$1")"
path2="$(readlink -e "$2")"
EBADARGS=65
function checkArgsNumber()
{
if test "$#" -ne 2; then
echo "ERRORE: this script takes exactly 2 params."
exit $EBADARGS
fi
}
function checkExistence()
{
if [ ! -d $path1 ]; then
echo "ERROR: "$1" does not exist"
exit $EBADARGS
elif [ ! -d "$2" ]; then
echo "ERROR: "$2" does not exist"
exit $EBADARGS
elif [[ -L $path1 ]]; then
echo "ERROR: path1 can't be a symbolic link"
exit $EBADARGS
elif [[ -L $2 ]]; then
echo "ERROR: path2 can't be a symbolic link"
exit $EBADARGS
fi
}
function checkIfSame()
{
if [[ $path1 == $path2 ]]; then
echo "ERROR: path1 and path2 must be different directories"
exit $EBADARGS
fi
}
function checkIfSubdirectories()
{
if [[ $path1 = *$path2* ]]; then
echo "ERROR:"$1" is a $path2 subdirectory"
exit $EBADARGS
elif [[ $path2 = *$path1* ]]; then
echo "ERROR:"$2" is a $path1 subdirectory"
exit $EBADARGS
elif [[ -e "$(find $path1 -samefile $path2)" ]]; then
echo "ERROR:"$(find $path1 -samefile $path2 -print0)" and "$2" have the same inode, $path2 is a $path1 subdirectory"
exit $EBADARGS
elif [[ -e "$(find $path2 -samefile $path1)" ]]; then
echo "ERROR:"$(find $path2 -samefile $path1 -print0)" and "$2" have the same inode, $path1 is a $path2 subdirectory"
exit $EBADARGS
fi
}
checkArgsNumber "$#"
checkExistence "$#"
checkIfSame "$#"
checkIfSubdirectories "$#"
now.. this should work and I hope it is useful somehow.
Could someone explain me how the *$path2* part works? What is the name of this * * operator? Where should I go read about it?
Some problems:
Stylistic
You should probably quote the entire argument to echo, as
echo "ERROR: $1 is a subdirectory of $(readlink -e "$2")"
Without the quotes around the argument to echo, you are technically passing each word as its own parameter: echo "ERROR:somedir" "is" "a" "subdirectory".... Since echo prints its parameters in the order given, separated by spaces, the output is the same in your case. But semantically it's not what you want.
(An example where it would be different:
echo foo bar
would print foo bar.)
Error message doesn't work properly
If the arguments don't exist
$ ./check.sh nonexistent1 nonexistent2
ERROR:nonexistent1 is a subdirectory of
Obviously, this is irrelevant if you've already checked they exist.
You similarly need to check for corner cases such as where the parameters refer to the same directory:
$ mkdir a b
$ ln -s ../a b/c
$ ./check.sh a b/c
ERROR:a is a subdirectory of /dev/shm/a
Doesn't detect symbolic links
$ mkdir a b
$ ln -s ../a b/c
$ ./check.sh a b
gives no error message.
Doesn't detect mount --bind
$ mkdir a b b/c
$ sudo mount --bind a b/c
$ ./check.sh a b
gives no error message.

Resources