I have many javascript files in my solaris server which have some debug, print and trace statements which I want to comment. There are hundreds of file like this.
I have found a script to do this but the problem is the script is removing the urhk_b2k_printRepos statement instead of commenting it. The script is as below:
if [ $# -ne 2 ]
then
echo "usage: prdel <script file name> <directory in which scripts are present>"
exit 1
fi
file=$1
dir=$2
if [ ! -s ${file} ]
then
echo "script file ${file} either does not exist or is empty (zero bytes)"
echo "Exiting..."
exit 1
fi
if [ ! -d ${dir} ]
then
echo "Invalid directory ${dir} entered"
echo "Exiting..."
exit 1
fi
cordir="./corrected"
prlogdir="./prlog"
if [ -d ${cordir} ]
then
echo "The corrected directory exist in the path, Please remove and run the tool again"
echo "Exiting..."
exit 1
else
mkdir ${cordir}
fi
if [ -d ${prlogdir} ]
then
echo "The prlog directory exist in the path, Please remove and run the tool again"
echo "Exiting..."
exit 1
else
mkdir ${prlogdir}
fi
errFile="$prlogdir/scr_err.rpt"
sucFile="$prlogdir/scr_suc.rpt"
Lines=`wc -l $file`
cntr=1
while [ $cntr -le $Lines ]
do
src=`head -$cntr $file|tail -1`
echo "$cntr. Processing $src...."
srcPath="${dir}/${src}"
if [ ! -s ${srcPath} ]
then
echo "Script file ${src} does not exist in the path given" >> ${errFile}
else
cp $srcPath $cordir/$src.tmp
srctemp="$cordir/$src.tmp"
srccor="$cordir/$src.corrected"
printcnt=`grep -ci "^[ ]*print" $srctemp`
if [ $printcnt -ne 0 ]
then
cat $srctemp|sed 's/^[ ]*[ ]*print[ ]*(/#print(/'|sed 's/^[ ]*[ ]*PRINT[ ]*(/#PRINT(/' > $srccor
mv $srccor $srctemp
fi
prreposcnt=`grep -ci "printrepos" $srctemp`
if [ $prreposcnt -ne 0 ]
then
cat $srctemp|sed 's/^.*urhk_b2k_printRepos.*/#Printrepos statement removed/'|sed 's/^.*urhk_B2k_PrintRepos.*/#Printrepos statement removed/'|sed 's/^.*urhk_B2k_printRepos.*/#Printrepos statement removed/'|sed 's/^.*urhk_b2k_PrintRepos.*/#Printrepos statement removed/' > $srccor
else
cp $srctemp $srccor
fi
echo "Script file $src correction is done" >> ${sucFile}
rm $srctemp
diff $srcPath $srccor >> $prlogdir/$src.diff.rpt
fi
cntr=`expr $cntr + 1`
done
echo "done"
I am completely new to shell scripting. Can anyone help me to modify this script to comment "urhk_b2k_printRepos" lines and also comment "TRACE ON" lines.
Related
I have a homework using for loop but I'm not quite understand the task that I have to do in there. I wrote a script but I feel like it's not a correct script. Please help!
Here is the question:
Write a shell script to list out the contents of any directory, and indicate for each file (including invisible ones) whether the file is a directory, a plain file, and whether it is public and/or executable to this process
#!/bin/bash
if [ $# -lt 1 ] ; then
echo " file doesn't exist"
echo
echo " variable needed to run a command"
fi
echo ---------------------------------------------
echo ---------------------------------------------
for i in $*
do
if [ -f $i ]; then
echo " it's a file";
echo "THIS IS A LIST OF FILE and DIRECTORY in $i"
ls -a $i
fi
done
echo -----------------------------------------
if [ -d $i ]; then
echo "directory" ;
echo "THIS IS A LIST OF FILES AND DIRETORY in $i"
ls -a $i
fi
echo ------------------------------------------
if [ -x $i ]; then
echo "executable"
echo "THIS IS A LIST OF EXECUTABLE FILE IN $i"
ls -x $i
fi
echo -----------------------------------------
if [ -r $i ]; then
echo "this file is a public file"
else "this is a private file"
fi
#!/bin/bash
if [ $# -lt 1 ] ; then
echo " file doesn't exist"
echo
echo " variable needed to run a command"
fi
echo ---------------------------------------------
echo ---------------------------------------------
for i in $*
do
if [ -f $i ]; then
echo " it's a file";
echo "THIS IS A LIST OF FILE and DIRECTORY in $i"
ls -a $i
fi
done
echo -----------------------------------------
if [ -d $i ]; then
echo "directory" ;
echo "THIS IS A LIST OF FILES AND DIRETORY in $i"
ls -a $i
fi
echo ------------------------------------------
if [ -x $i ]; then
echo "executable"
echo "THIS IS A LIST OF EXECUTABLE FILE IN $i"
ls -x $i
fi
echo -----------------------------------------
if [ -r $i ]; then
echo "this file is a public file"
else "this is a private file"
fi
Poorly written specifications are the bane of education. "Public" sounds like the wrong word here. I'll assume it means "readable".
You check if there's an argument, but you don't exit the program if there is not. I'd also confirm it's a directory, and readable.
The manual will do you a lot of good. Expect to do a lot of reading till you learn this stuff, and then reference it a lot to be sure.
Read this section carefully, create some tests for yourself to prove they work and that you understand them, and your job will be more than half done.
Don't use [. Generally it's just better to always use [[ instead, unless you are using (( or case or some other construct.
I don't see that a for loop was specified, but it ought to be fine. Just be aware that you might have to specify $1/* and $1/.* separately.
Put all your tests in one loop, though. For each file, test for whether it's a directory - if it is, report it. Test if it's a plain file - if it is, report it.
I do NOT like doing homework for someone, but it looks like you could use an example that simplifies this. I recommend you not use this as written - break it out and make it clearer, but this is a template for the general logic.
#! /bin/env bash
(( $# )) && [[ -d "$1" ]] && [[ -r "$1" ]] || {
echo "use: $0 <dir>" >&2
exit 1
}
for e in "$1"/.* "$1"/*
do echo "$e:"
[[ -d "$e" ]] && echo " is a directory"
[[ -f "$e" ]] && echo " is a plain file"
[[ -r "$e" ]] && echo " is readable"
[[ -x "$e" ]] && echo " is executable"
done
If you read the links I provided you should be able to break this apart and understand it.
Generally, your script is long and a bit convoluted. Simpler is easier to understand and maintain. For example, be very careful about block indentation to understand scope.
$: for i in 1 2 3
> do echo $i
> done
1
2
3
$: echo $i
3
Compare this to -
for i in $*
do if [ -f $i ]; then
echo " it's a file";
echo "THIS IS A LIST OF FILE and DIRECTORY in $i"
ls -a $i
fi
done
echo -----------------------------------------
if [ -d $i ]; then
echo "directory" ;
echo "THIS IS A LIST OF FILES AND DIRETORY in $i"
ls -a $i
fi
You are testing each entry to see if it is a file, and if it is, reporting "THIS IS A LIST OF FILE and DIRECTORY in $i" every time...
but then only testing the last one to see if it's a directory, because the [ -d $i ] is after the done.
...did you run this somewhere to try it, and look at the results?
I have a working script that parses a text file and creates a new file from the output. How do I run this script against a single file OR a directory of files instead? Below is a general overview of the working script. Thank you for the help.
#!/usr/bin/env bash
if [ -f "$1" ]; then
*Run Some Commands against file* "$1" >> NewFile.txt
echo "Complete. Check NewFile.txt"
else
echo "Expected a file at $1, but it doesn't exist." >&2
fi
You could check if the passed argument is a directory and if so, write a loop to process the files in that directory:
#!/usr/bin/env bash
if (($# = 0)); then
echo "No arguments given" >&2
exit 2
fi
arg=$1
if [ -f "$arg" ]; then
*Run Some Commands against file* "$1" >> NewFile.txt
echo "Complete. Check NewFile.txt"
elif [ -d "$arg" ]; then
shopt -s nullglob
for file in "$arg"/*; do
# run command against "$file"
done
else
echo "Expected a file or directory as $1, but it doesn't exist." >&2
fi
An easier solution (which also recurses) is making it X-dimensional:
#!/usr/bin/env bash
if [ -d $1 ]; then
for i in $1/*; do
# start another instance of this script
$0 $1/$i
done
fi
if [ -f "$1" ]; then
*Run Some Commands against file* "$1" >> NewFile.txt
echo "Complete. Check NewFile.txt"
else
echo "Expected a file at $1, but it doesn't exist." >&2
fi
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
I'm trying to write an extremely simple script in Ubuntu which would allow me to pass it either a filename or a directory, and be able to do something specific when it's a file, and something else when it's a directory. The problem I'm having is when the directory name, or probably files too, has spaces or other escapable characters are in the name.
Here's my basic code down below, and a couple tests.
#!/bin/bash
PASSED=$1
if [ -d "${PASSED}" ] ; then
echo "$PASSED is a directory";
else
if [ -f "${PASSED}" ]; then
echo "${PASSED} is a file";
else
echo "${PASSED} is not valid";
exit 1
fi
fi
And here's the output:
andy#server~ $ ./scripts/testmove.sh /home/andy/
/home/andy/ is a directory
andy#server~ $ ./scripts/testmove.sh /home/andy/blah.txt
/home/andy/blah.txt is a file
andy#server~ $ ./scripts/testmove.sh /home/andy/blah\ with\ a\ space.txt
/home/andy/blah with a space.txt is not valid
andy#server~ $ ./scripts/testmove.sh /home/andy\ with\ a\ space/
/home/andy with a space/ is not valid
All of those paths are valid, and exist.
That should work. I am not sure why it's failing. You're quoting your variables properly. What happens if you use this script with double [[ ]]?
if [[ -d $PASSED ]]; then
echo "$PASSED is a directory"
elif [[ -f $PASSED ]]; then
echo "$PASSED is a file"
else
echo "$PASSED is not valid"
exit 1
fi
Double square brackets is a bash extension to [ ]. It doesn't require variables to be quoted, not even if they contain spaces.
Also worth trying: -e to test if a path exists without testing what type of file it is.
At least write the code without the bushy tree:
#!/bin/bash
PASSED=$1
if [ -d "${PASSED}" ]
then echo "${PASSED} is a directory";
elif [ -f "${PASSED}" ]
then echo "${PASSED} is a file";
else echo "${PASSED} is not valid";
exit 1
fi
When I put that into a file "xx.sh" and create a file "xx sh", and run it, I get:
$ cp /dev/null "xx sh"
$ for file in . xx*; do sh "$file"; done
. is a directory
xx sh is a file
xx.sh is a file
$
Given that you are having problems, you should debug the script by adding:
ls -ld "${PASSED}"
This will show you what ls thinks about the names you pass the script.
Using -f and -d switches on /bin/test:
F_NAME="${1}"
if test -f "${F_NAME}"
then
echo "${F_NAME} is a file"
elif test -d "${F_NAME}"
then
echo "${F_NAME} is a directory"
else
echo "${F_NAME} is not valid"
fi
Using the "file" command may be useful for this:
#!/bin/bash
check_file(){
if [ -z "${1}" ] ;then
echo "Please input something"
return;
fi
f="${1}"
result="$(file $f)"
if [[ $result == *"cannot open"* ]] ;then
echo "NO FILE FOUND ($result) ";
elif [[ $result == *"directory"* ]] ;then
echo "DIRECTORY FOUND ($result) ";
else
echo "FILE FOUND ($result) ";
fi
}
check_file "${1}"
Output examples :
$ ./f.bash login
DIRECTORY FOUND (login: directory)
$ ./f.bash ldasdas
NO FILE FOUND (ldasdas: cannot open `ldasdas' (No such file or directory))
$ ./f.bash evil.php
FILE FOUND (evil.php: PHP script, ASCII text)
FYI: the answers above work but you can use -s to help in weird situations by checking for a valid file first:
#!/bin/bash
check_file(){
local file="${1}"
[[ -s "${file}" ]] || { echo "is not valid"; return; }
[[ -d "${file}" ]] && { echo "is a directory"; return; }
[[ -f "${file}" ]] && { echo "is a file"; return; }
}
check_file ${1}
Using stat
function delete_dir () {
type="$(stat --printf=%F "$1")"
if [ $? -ne 0 ]; then
echo "$1 directory does not exist. Nothing to delete."
elif [ "$type" == "regular file" ]; then
echo "$1 is a file, not a directory."
exit 1
elif [ "$type" == "directory" ]; then
echo "Deleting $1 directory."
rm -r "$1"
fi
}
function delete_file () {
type="$(stat --printf=%F "$1")"
if [ $? -ne 0 ]; then
echo "$1 file does not exist. Nothing to delete."
elif [ "$type" == "directory" ]; then
echo "$1 is a regular file, not a directory."
exit 1
elif [ "$type" == "regular file" ]; then
echo "Deleting $1 regular file."
rm "$1"
fi
}
https://linux.die.net/man/2/stat
https://en.m.wikipedia.org/wiki/Unix_file_types
A more elegant solution
echo "Enter the file name"
read x
if [ -f $x ]
then
echo "This is a regular file"
else
echo "This is a directory"
fi
Answer based on the title:
Check if passed argument is file or directory in Bash
This works also if the provided argument has a trailing slash .e.g. dirname/
die() { echo $* 1>&2; exit 1; }
# This is to remove the the slash at the end: dirName/ -> dirName
fileOrDir=$(basename "$1")
( [ -d "$fileOrDir" ] || [ -f "$fileOrDir" ] ) && die "file or directory $fileOrDir already exists"
Testing:
mkdir mydir
touch myfile
command dirName
# file or directory mydir already exists
command dirName/
# file or directory mydir already exists
command filename
# file or directory myfile already exists
#!/bin/bash
echo "Please Enter a file name :"
read filename
if test -f $filename
then
echo "this is a file"
else
echo "this is not a file"
fi
One liner
touch bob; test -d bob && echo 'dir' || (test -f bob && echo 'file')
result is true (0)(dir) or true (0)(file) or false (1)(neither)
This should work:
#!/bin/bash
echo "Enter your Path:"
read a
if [[ -d $a ]]; then
echo "$a is a Dir"
elif [[ -f $a ]]; then
echo "$a is the File"
else
echo "Invalid path"
fi
I want to check if file2.sh exists and also if a specific word, poet is part of the file. I use grep to create the variable used_var.
#!/bin/ksh
file_name=/home/file2.sh
used_var=`grep "poet" $file_name`
How can I check if used_var has some value?
Instead of storing the output of grep in a variable and then checking whether the variable is empty, you can do this:
if grep -q "poet" $file_name
then
echo "poet was found in $file_name"
fi
============
Here are some commonly used tests:
-d FILE
FILE exists and is a directory
-e FILE
FILE exists
-f FILE
FILE exists and is a regular file
-h FILE
FILE exists and is a symbolic link (same as -L)
-r FILE
FILE exists and is readable
-s FILE
FILE exists and has a size greater than zero
-w FILE
FILE exists and is writable
-x FILE
FILE exists and is executable
-z STRING
the length of STRING is zero
Example:
if [ -e "$file_name" ] && [ ! -z "$used_var" ]
then
echo "$file_name exists and $used_var is not empty"
fi
if test -e "$file_name";then
...
fi
if grep -q "poet" $file_name; then
..
fi
test -e will test whether a file exists or not. The test command returns a zero value if the test succeeds or 1 otherwise.
Test can be written either as test -e or using []
[ -e "$file_name" ] && grep "poet" $file_name
Unless you actually need the output of grep you can test the return value as grep will return 1 if there are no matches and zero if there are any.
In general terms you can test if a string is non-empty using [ "string" ] which will return 0 if non-empty and 1 if empty
If you have the test binary installed or ksh has a matching built-in function, you could use it to perform your checks. Usually /bin/[ is a symbolic link to test:
if [ -e "$file_name" ]; then
echo "File exists"
fi
if [ -z "$used_var" ]; then
echo "Variable is empty"
fi
You should use the grep -q flag for quiet output. See the man pages below:
man grep output :
General Output Control
-q, --quiet, --silent
Quiet; do not write anything to standard output. Exit immediately with zero status
if any match is found, even if an error was detected. Also see the -s or
--no-messages option. (-q is specified by POSIX.)
This KornShell (ksh) script demos the grep quiet output and is a solution to your question.
grepUtil.ksh :
#!/bin/ksh
#Initialize Variables
file=poet.txt
var=""
dir=tempDir
dirPath="/"${dir}"/"
searchString="poet"
#Function to initialize variables
initialize(){
echo "Entering initialize"
echo "Exiting initialize"
}
#Function to create File with Input
#Params: 1}Directory 2}File 3}String to write to FileName
createFileWithInput(){
echo "Entering createFileWithInput"
orgDirectory=${PWD}
cd ${1}
> ${2}
print ${3} >> ${2}
cd ${orgDirectory}
echo "Exiting createFileWithInput"
}
#Function to create File with Input
#Params: 1}directoryName
createDir(){
echo "Entering createDir"
mkdir -p ${1}
echo "Exiting createDir"
}
#Params: 1}FileName
readLine(){
echo "Entering readLine"
file=${1}
while read line
do
#assign last line to var
var="$line"
done <"$file"
echo "Exiting readLine"
}
#Check if file exists
#Params: 1}File
doesFileExit(){
echo "Entering doesFileExit"
orgDirectory=${PWD}
cd ${PWD}${dirPath}
#echo ${PWD}
if [[ -e "${1}" ]]; then
echo "${1} exists"
else
echo "${1} does not exist"
fi
cd ${orgDirectory}
echo "Exiting doesFileExit"
}
#Check if file contains a string quietly
#Params: 1}Directory Path 2}File 3}String to seach for in File
doesFileContainStringQuiet(){
echo "Entering doesFileContainStringQuiet"
orgDirectory=${PWD}
cd ${PWD}${1}
#echo ${PWD}
grep -q ${3} ${2}
if [ ${?} -eq 0 ];then
echo "${3} found in ${2}"
else
echo "${3} not found in ${2}"
fi
cd ${orgDirectory}
echo "Exiting doesFileContainStringQuiet"
}
#Check if file contains a string with output
#Params: 1}Directory Path 2}File 3}String to seach for in File
doesFileContainString(){
echo "Entering doesFileContainString"
orgDirectory=${PWD}
cd ${PWD}${1}
#echo ${PWD}
grep ${3} ${2}
if [ ${?} -eq 0 ];then
echo "${3} found in ${2}"
else
echo "${3} not found in ${2}"
fi
cd ${orgDirectory}
echo "Exiting doesFileContainString"
}
#-----------
#---Main----
#-----------
echo "Starting: ${PWD}/${0} with Input Parameters: {1: ${1} {2: ${2} {3: ${3}"
#initialize #function call#
createDir ${dir} #function call#
createFileWithInput ${dir} ${file} ${searchString} #function call#
doesFileExit ${file} #function call#
if [ ${?} -eq 0 ];then
doesFileContainStringQuiet ${dirPath} ${file} ${searchString} #function call#
doesFileContainString ${dirPath} ${file} ${searchString} #function call#
fi
echo "Exiting: ${PWD}/${0}"
grepUtil.ksh Output :
user#foo /tmp
$ ksh grepUtil.ksh
Starting: /tmp/grepUtil.ksh with Input Parameters: {1: {2: {3:
Entering createDir
Exiting createDir
Entering createFileWithInput
Exiting createFileWithInput
Entering doesFileExit
poet.txt exists
Exiting doesFileExit
Entering doesFileContainStringQuiet
poet found in poet.txt
Exiting doesFileContainStringQuiet
Entering doesFileContainString
poet
poet found in poet.txt
Exiting doesFileContainString
Exiting: /tmp/grepUtil.ksh