Why is awk command not working in shell script [duplicate] - bash

I have written a bash script that gets three paths based on input parameters and then then gets the imagename/filename in the path.
Something like:
I provide:
AA=/home/user
Then it uses the find command to get
/home/user/dir2/images/dir/tellmeimage1fun.bin
Finally I have to get tellmeimage1fun.bin as output.
Script:
#!/bin/bash
echo "arg0 n/k/d"
AA=$1
CC=$3
PATH1="`find $AA/dir2/images/dir/ -name *image1*.bin`"
PATH2="`find $AA/dir2/images/dir/ -name *bimage2*.bin`"
PATH3="`find $AA/dir2/images/dir/ -name *cimage3*.bin`"
if [ $CC = "n" ] ; then
PATH=$PATH1
elif [ $CC = "k" ] ; then
PATH=$PATH2
else
PATH=$PATH3
fi
#Getting filename name from path:
IMG="`ls $PATH | cut -d "/" -f6`"
OUTPUT:
/users/prasapat/bin/sl5: line 22: ls: command not found
/users/prasapat/bin/sl5: line 22: cut: command not found
If I give complete paths to ls and cut they work. But i don't want to do that for all commands in the script. If i remove the last line and echo the PATH variable it is completely fine. Only after adding the last command, I see the problem.
What am I doing wrongly?

The problem is that you are redefining the PATH variable where bash looks into to find the binary files if you don't use a complete path when calling.
You should change the PATH in your bash script to MYPATH or something like that, so that it doesn't mess with the already environmental variables.
If you don't know what the PATH variable is for you can look at wikipedia's article

I had this problem, turns out editing a bash script using Notepad++ was adding DOS line endings instead of UNIX line endings. Running the script in a Linux environment was causing the 'command not found' error to be thrown.
Managed to diagnose the problem by running my script like so:
bash -x testscript.sh
Which will dump any compiler output. The error message that gets thrown is:
bash -x testscript.sh
+ $'\r'
: command not found 2:
'estscript.sh: line 3: syntax error near unexpected token `{
I fixed the issue by changing the formatting of line endings in Notepad++ to be UNIX not DOS by going Edit -> EOL Conversion -> UNIX.

$PATH is a special environment variable that contains a list of directories where your shell (in this case, bash) should look in when you type a command (such as find and ls.) Just try echo $PATH in a script or in a shell to get a feeling of what it looks like (you will typically have /bin, /usr/bin and /usr/local/bin listed there, maybe more.)
As you don't really need to redefine this variable in this particular script, you should use another name than $PATH.

$PATH is a predefined variable which gives the directories to search when looking for executables. Pick a different variable name for your script and you'll be fine.

Use a different variable name than PATH. $PATH is the environment variable which tells your shell where to look for executables (so, e.g., you can run ls instead of /bin/ls).

You are using the PATH that is special and used to locate the commands and that is why ls can't be resolved. Use any name other than PATH
if [ $CC = "n" ] ; then
MY_PATH=$PATH1
elif [ $CC = "k" ] ; then
MY_PATH=$PATH2
else
MY_PATH=$PATH3
fi
export MY_PATH
IMG="`ls $MY_PATH | cut -d "/" -f6`"

Related

bash for loop in python crashed [duplicate]

I am a beginner of bash. I encounter a problem like this:
$ "make -p"
when I type the above in bash command line, there is nothing to happen, no error, no result msg.
I have searched double quotes syntax of bash in many websites. All of these materials give similar interpretation as below:
https://www.gnu.org/software/bash/manual/html_node/Double-Quotes.html
and give examples like:
echo "argument"
I do not find something like "echo argument". Moreover, I find a strange difference between bash command line and bash scripts.
If I type a non-existing command in command line:
$ "holy shit"
$ "look that"
there is nothing to happen. But if I type it in bash scripts:
#!/bin/bash
"holy shit"
"look that"
and execute this script, an error msg will be throw out:
$ ./myshell
./myshell: line 2: holy shit: command not found
./myshell: line 3: look that: command not found
Would someone can help give a detailed interpretation about the effect of double quotes when they enclosed the whole command?
Why there is no output in command-line?
Why it is different between command line and scripts?
If you enter a command foo, the shell searches the directories listed in your PATH variable until it finds a command of this name. If there is none, you get the error message command not found.
If you enter a command, which contains at least one slash - for example ./foo or foo/bar -, the shell does not search the PATH, but assumes that you have already entered the correct path to your command. If it does not exist, you get the error message No such file or directory.
In your case,
"cd home"
searches for a file with name cd home somewhere along your PATH, but there is no file of this name, and you get command not found. If you enter
"cd /home"
the shell bypasses PATH-search and assumes, that there exists a directory named cd (i.e. the 3 letters c,d,space) in your current directory, and below it a file named home, with x-bit set. There is no such file (and no such directory) on your system, and you get the error message No such file or directory.
If you are in the mood of experimenting around, you could try the following:
mydir="cd "
mkdir "$mydir"
echo "echo Hello Stranger" >"$mydir/home"
chmod +x "$mydir/home"
"cd /home"
This should print Hello Stranger. Pay attention that in the assignment to mydir, there must be a single space between the cd and the closing quote.
The double quotes mean it is a string. You can do something like:
echo "Hello everybody"
either at the command line or the shell. Sometimes when people put stuff in quotes. you are supposed to replace what is in quotes with your own variable (removing the quotes), and sometimes people put quotes around the whole command you are supposed to type to show the what exactly you should type. For your example of "make -p" just type it without the quotes and it should work in both the command line and as a script.

scp error when defining a "PATH" variable in a bash script

So this is my script
#!/bin/bash
PATH=/SomeFolder/file2.txt;
scp -3 user#server1:/SomeFolder/file.txt user#server2:$PATH;
I get this error
main.sh: line 3: scp: command not found
If I put /SomeFolder/file2.txt in place of of "$PATH" it still doesn't work - same error. It's only after I remove entire second line (PATH definition) does it work.
I simplified my script, the PATH is defined by executing a script inside another server but that doesn't matter. I tested it like what you see and I concluded that the error is due to PATH being defined in the first place.
It is happening because PATH is a system variable that defines directories where the programs and scripts should be looked for. You can view its value by executing echo $PATH. In your script you are setting PATH to /SomeFolder/file2.txt so the program scp that is usually in /usr/bin/ can't be found. Just change the name of variable PATH in your script to something else.

Shell script syntax error: unexpected end of line

I wrote a simple shell script to check for the existence of a xml file and if it exists, then rename an old xml file to be backup and then move the new xml file to where the old xml file was stored.
#!/bin/sh
oldFile="/Documents/sampleFolder/sampleFile.xml"
newFile="/Documents/sampleFile.xml"
backupFileName="/Documents/sampleFolder/sampleFile2.backup"
oldFileLocation="/Documents/sampleFolder"
if [ -f "$newFile" ] ; then
echo "File found"
#Rename old file
mv $oldFile $backupFileName
#move new file to old file's location
mv $newFile $oldFileLocation
else
echo "File not found, do nothing"
fi
However, every time I try to run the script, I get 4 command not found messages and a syntax error: unexpected end of file. Any suggestions on why I get these command not found errors or the unexpected end of file? I double checked that I closed all my double quotes, I have code highlight :)
EDIT:
output from running script:
: command not found:
: command not found:
: command not found1:
: command not found6:
replaceXML.sh: line 26: syntax error: unexpected end of file
I believe you're running on Cygwin. There's more to the error messages than what you're seeing:
: command not found:
: command not found:
: command not found1:
: command not found6:
replaceXML.sh: line 26: syntax error: unexpected end of file
You probably used a Windows editor to create the script file, which means it uses Windows-style CR-LF ("\r\n") line endings, rather than Unix-style LF ('\n') line endings. Some programs under Cygwin can handle either form, but the shell doesn't.
For example, the line that looks like
then
looks to the shell like
then^M
where ^M is the ASCII CR character. This would actually be a valid command name if it existed, but it doesn't, so the shell complains:
then^M: command not found
But printing the CR character causes the cursor to go back to the beginning of the line, so everthing before the : is overwritten.
You're getting the "unexpected end of file" message because the shell never saw a fi to match the if.
You can use the dos2unix command to fix the line endings. Be sure to read the man page (man dos2unix); unlike most text filters, dos2unix replaces its input file rather than writing to stdout.
I can't really see anything wrong with your code apart from then not being in a legal place for older shells. Also notice the quotes around arguments to mv (but that should not be a problem if the files are named properly).
Try this:
#!/bin/sh
oldFile="/Documents/sampleFolder/sampleFile.xml"
newFile="/Documents/sampleFile.xml"
backupFileName="/Documents/sampleFolder/sampleFile2.backup"
oldFileLocation="/Documents/sampleFolder"
if [ -f "$newFile" ]
then
echo "File found"
mv "$oldFile" "$backupFileName"
mv "$newFile" "$oldFileLocation"
else
echo "File not found, do nothing"
fi
PS: verify that /bin/sh is (or points to) a bourne based shell.
What I did in my case:
I used Bash On Ubuntu on Windows (in Windows 10) instead of Cygwin and then installed dos2unix using sudo apt-get install dos2unixand used the following command to fix this problem:
$ dos2unix < compilelibs.sh > output.sh

Deleting a directory contents using shell scripts

I am a newbie to Shell scripting. I want to delete all the contents of a directory which is in HOME directory of the user and deleting some files which are matching with my conditions. After googled for some time, i have created the following script.
#!/bin/bash
#!/sbin/fuser
PATH="$HOME/di"
echo "$PATH";
if [ -d $PATH ]
then
rm -r $PATH/*
fuser -kavf $PATH/.n*
rm -rf $PATH/.store
echo 'File deleted successfully :)'
fi
If I run the script, i am getting error as follows,
/users/dinesh/di
dinesh: line 11: rm: command not found
dinesh: line 12: fuser: command not found
dinesh: line 13: rm: command not found
File deleted successfully :)
Can anybody help me with this?
Thanks in advance.
You are modifying PATH variable, which is used by the OS defines the path to find the utilities (so that you can invoke it without having to type the full path to the binary). The system cannot find rm and fuser in the folders currently specified by PATH (since you overwritten it with the directory to be deleted), so it prints the error.
tl;dr DO NOT use PATH as your own variable name.
PATH is a special variable that controls where the system looks for command executables (like rm, fuser, etc). When you set it to /users/dinesh/di, it then looks there for all subsequent commands, and (of course) can't find them. Solution: use a different variable name. Actually, I'd recommend using lowercase variables in shell scripts -- there are a number of uppercase reserved variable names, and if you try to use any of them you're going to have trouble. Sticking to lowercase is an easy way to avoid this.
BTW, in general it's best to enclose variables in double-quotes whenever you use them, to avoid trouble with some parsing the shell does after replacing them. For example, use [ -d "$path" ] instead of [ -d $path ]. $path/* is a bit more complicated, since the * won't work inside quotes. Solution: rm -r "$path"/*.
Random other notes: the #!/sbin/fuser line isn't doing anything. Only the first line of the script can act as a shebang. Also, don't bother putting ; at the end of lines in shell scripts.
#!/bin/bash
path="$HOME/di"
echo "$path"
if [ -d "$path" ]
then
rm -r "$path"/*
fuser -kavf "$path"/.n*
rm -rf "$path/.store"
echo 'File deleted successfully :)'
fi
This line:
PATH="$HOME/di"
removes all the standard directories from your PATH (so commands such as rm that are normally found in /bin or /usr/bin are 'missing'). You should write:
PATH="$HOME/di:$PATH"
This keeps what was already in $PATH, but puts $HOME/di ahead of that. It means that if you have a custom command in that directory, it will be invoked instead of the standard one in /usr/bin or wherever.
If your intention is to remove the directory $HOME/di, then you should not be using $PATH as your variable. You could use $path; variable names are case sensitive. Or you could use $dir or any of a myriad other names. You do need to be aware of the key environment variables and avoid clobbering or misusing them. Of the key environment variables, $PATH is one of the most key ($HOME is another; actually, after those two, most of the rest are relatively less important). Conventionally, upper case names are reserved for environment variables; use lower case names for local variables in a script.

Find file's own path

I'm trying to find what the unix equivalent of the Windows/DOS variable %cd% is. What I'm looking for is an environmental variable or a workaround that will let me set a variable to the path of the file currently running.
For example, if the program is in /home/chris/Desktop but the working directory is /home/chris, what would be the command to get ~/Desktop as opposed to pwd which will give me /home/chris.
In BASH, you can look at the $PWDvariable. That'll show your Present Working Directory. Getting the relationship between the $PWD and where the program is located is a bit trickier. You can look at the $0 variable which should give you the name of the file I ran the following script:
#! /bin/bash
#
echo "PWD = $PWD"
echo "\$0 = $0"
And got the following result:
$ test.sh
PWD = /Users/david
$0 = /Users/david/bin/test.sh
The $0 gives you the name of the file from the root of the OS. Taking the dirname will give you the file name. Somehow, if you can filter out the PWD from the $0, you might get what you're looking for. I had some luck with the following:
curPath=$(dirname "${0#$PWD/}")
Didn't thoroughly test it, from what I can see, it seems to do what you want. What it can't do is do something like this:
$ test.sh
PWD = /Users/david/someSubDir
$0 = /Users/david/bin/test.sh
The current path is /Users/david/bin/test.sh
It would have been nice if it could do this:
The current path is ../bin/test.sh
Although the former is correct.
The readlink command doesn't work on non-Linux systems.
How about dirname $(readlink -f $0)
readlink -f $0 returns the canonicalized path to the running script.
dirname removes everything after and including the final \.
This way works, but isn't 100% reliable:
${0%/*}
The way that works is that it reads $0 (the program name), and strips off everything from the final slash onwards. It's not reliable because if your script is invoked via a symlink, you will get the directory containing the symlink, not the directory containing the real script.
Also, it's possible to pass in a "fake" value for $0, for example by using exec -a. So even if you aren't using symlinks, it's still not a 100% solution. In fact, such a solution doesn't exist.
Working with what Chris suggested, you could use the which command. According to the man page, which reports the full path of the executable that would have been executed if its argument had been entered at the shell prompt. Since we know $0 was entered at the shell prompt, we can use `which $0` to report exactly the path that was used to execute. Unfortunately, this still suffers from the symlink issue, as which does not provide options to avoid symlinks.

Resources