How to get rid of cygwin's path prefix - bash

In cygwin, in order to remove /cygdrive prefix in the paths, I did a mount like this -
mount -c /
after restarting cygwin, when I say pwd - it gives me something like - /c/Work/shared/imply-1.1.1 [actually per windows c:\Work\shared\imply-1.1.1]
and now I have a perl script that I am running using cygwin and I see an error ... something like - Error: Cannot find module 'C:\c\Work\shared\imply-1.1.1\dist\pivot\bin\pivot'
that additional /c/ which is a drive notion returned from cygwin is causing above error (at least one way of looking at it).
Any idea on how to get rid of that ?
Update: To give a better context to the above issue. Here is what is happening -
There is a script file, whose contents are as follows -
#!/bin/bash -eu
if [ "$#" -gt 1 ]
then
echo "usage: $0 [conf-dir]" >&2
exit 1
fi
PWD="$(pwd)"
WHEREAMI="$(dirname "$0")"
if [ "$#" -lt 1 ] || [ "x$1" = "x" ]
then
CONFDIR="$WHEREAMI"/../conf
else
CONFDIR="$1"
fi
CONFDIR="$(cd "$CONFDIR" && pwd)/pivot"
WHEREAMI="$(cd "$WHEREAMI" && pwd)"
When I echo the contents of the CONFDIR and WHEREAMI, I get the following -
C:\cygdrive\c\Work\shared\imply-1.1.1\conf\pivot
C:\cygdrive\c\Work\shared\imply-1.1.1\bin\
But the ${pwd} paths were supposed to be resolved as "c:\Work....."
So what I am doing wrong in cygwin?

Don't mount C:\ as / in Cygwin:
If this is any help for you, I was intent to use something similar to what you want ... I've tried, first on NT4, then on W2k, to setup a *NIX-like single-root filesystem, where C:\ is the only root, and every other device is a [sub]folder somewhere out there.
Guess, what? It didn't work ... You can't reliably use
CD/DVD drives, when they are not represented as disk letters, you can't
disconnect removable drives without first breaking the mount point ... it's just too much trouble to maintain.
Also, I have been mixing Cygwin, Strawberry, and custom MSVC builds of perl on the same machine for more than a decade now, and I do not understand how the /cygdrive prefix presents a problem.
In Cygwin Bash, the following works as expected:
$ ls D:/Src
In cmd.exe,
C:\Users> c:\opt\cygwin64\bin\perl -E "opendir $h, 'D:/Src'; say for readdir $h"
also works as expected.
See also the CYGWIN environment variable:
(no)dosfilewarning - If set, Cygwin will warn the first time a user uses an "MS-DOS" style path name rather than a POSIX-style path name. Defaults to off.

What about cygpath (Convert Unix and Windows format paths, or output system path information)...
$ pwd
/cygdrive/c/Windows/System32
$ cygpath -w $(pwd)
C:\Windows\System32

Related

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

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`"

OSX : absolute desktop file path ? (including /Volumes)

When I try to retrieve the path of a file on my desktop, I get :
/Users/MyName/Desktop/file.txt
But I need the full path (to feed a bash script):
/Volumes/MyDrive/Users/MyName/Desktop/file.txt
I spent quite some time searching for a solution, but couldn't find any.
I'm open to anything that can be run through Automator, bash or applescript.
It makes me crazy because if I simply drop my file.txt in Coda, it will output the full absolute path I want, right away, whereas Terminal won't.
Any ideas ?
So you need to find which volume under /Volumes is equivalent to /, yes? That's easy - just look for the symlink to /.
for vol in /Volumes/*; do
if [ "$(readlink "$vol")" = / ]; then
root_vol=$vol
fi
done
Then you can do
echo "$root_vol$HOME/Desktop/file.txt"
or whatever.
For anyone who might need it :
if you're running an OSX Automator workflow/application/service and needs an absolute path to your input file, simply add a "Run shell script" action, set the input "as arguments" and use the following :
#!/bin/bash
## Check if the input is an absolute path including the volume name
if [[ "$1" = /Volumes/* ]]
## If TRUE, the path is already correct
then
echo "$1"
## If FALSE, needs fixing
else
## Resolve the volume name
## by looping through all the volumes to find the one symlinked to "/"
for vol in /Volumes/*
do
if [ "$(readlink "$vol")" = / ]
then root_vol=$vol
fi
done
## Pass the path back to Automator for further use
echo "$root_vol$1"
fi

Strange PATH behavior in win-bash

I installed win-bash on Windows 7 and I'm getting the following strange behavior.
bash$ cat C:/Home/.bashrc
PATH="C:/Program\ Files/GnuWin32/bin:C:/Windows/system32"
bash$ . C:/Home/.bashrc
bash$ echo $PATH
C:/Program\ Files/GnuWin32/bin:C:/Windows/system32
bash$ which diff
which: no diff in (.;C;\Program\ Files\GnuWin32\bin;C:\Windows\system32)
bash$ which ls
which: no ls in (.;C;\Program\ Files\GnuWin32\bin;C:\Windows\system32)
Why are the PATH values different?
The PATH value returned by which contains .:C;\Program\ Files\GnuWin32\bin
Note:
the ".:" in the beginning that does not exist in the bash PATH value.
the "C;" (not C:) contains a semi-colon instead of a colon.
the which PATH value has back slashes (\\) instead of forward slashes (/)
Where is which sourcing these PATH values?
I can not find any other .bashrc or .profile or profile files anywhere on the machine.
In addition,
bash$ diff file-abc.txt file-xyz.txt
1c1
< abc
---
\> xyz
bash$ ls file-abc.txt
file-abc.txt
Both diff and ls work on the command line even though which can not find the diff or ls commands.
Both diff and ls are located in C:/Program\ Files/GnuWin32/bin
But which returns C;\Program\ Files\GnuWin32\bin (note C; not C:) which is why which can not find ls or diff.
Again, where is which sourcing these PATH values?
In my bash script named Try1.sh I have these lines.
\`diff $CURRENT_FILE $NEW_FILE\`
\`ls $CURRENT_FILE\`
The diff command fails with
Try1.sh: 21c21: command not found
The ls command succeeds. Why?
Both diff and ls live in the same PATH location C:/Program\ Files/GnuWin32/bin.
Windows has a different search algorithm to UNIX-like systems. On Windows the first directory to be searched is the directory which the parent program (.exe) was loaded from, then the current directory, then C:/Windows/system32 is searched. That's where the directory names are coming from.
The path environment variable is only used as a last resort!
For a full discussion on this, see MSDN entry for CreateProcess
which is also showing the Windows path directory separator as ;, rather than : which UNIX-like systems use. Also, / or \ are valid as a directory separator in a Windows path, but only / is valid on UNIX.
Also note that environment variables (like path) are not case sensitive on Windows, but on UNIX they are.
EDIT: I have been trying to track down the source code for win-bash but can't find it. I found some source code for which in GNUUtils, but can't be sure that it is the same version as you are using. The version I looked at, 2.4, makes assumptions about Windows which are not necessarily correct.
After downloading the binary for win-bash, I found that the bundled which is indeed version 2.4, and looks the same as the source code I have been looking at.
It is a separate program and not integrated with the rest of the shell code. To answer the question on directory separators and path separators, they are hard-coded for Windows (sys.h):
#define DIRSEP '\\'
#define PATHSEP ';'
The path is read from the environment variable using getenv.
Further edit:
The command
\`diff $CURRENT_FILE $NEW_FILE\`
is invalid. It is capturing the output from diff and then trying to execute it. 21c21 is the output from diff, and of course there is no such program as 21c21. Just use:
diff $CURRENT_FILE $NEW_FILE

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