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
Related
I'm writing my first bash script as part of homework and given covid 19 we haven't been able to go over some of this stuff in class (and I'm not doing well googling).
I am writing a script that takes user input and searches the cd to find a file with the name of $userInput. If found the script will determine if the file is a "normal file" (.txt for example) or if the file is a directory. How can I gather this information?
Here is my code currently:
#! /bin/bash
$userInput
echo "Enter a file name. Empty to exit."
while [ 1 ]
do
echo "Please input a file name:"
read userInput
if [ "$userInput" == "" ]; then
exit
else
echo $userInput
fi
done
I have the looping and getting user input down, what am I missing here?
if cd $userInput*; then
cd ..
echo "It is a directory."
else
# the cd will do the rest of informing for you
fi
I also strongly suggest to turn this into a file and get user input in command line, like this:
bash ./yourcode.sh filename
Inside your code:
if cd $1*; then
cd ..
echo "It is a directory."
else
# the cd will do the rest of informing for you
fi
EDITED: EXTRA
Continue here if you really wanna understand what happened. In bash, every command/function by default returns a value that informs the kernel whether it terminated successfully or something went wrong, for sake of simplicity, we will just assume it returns true if successful and false if not, here I used this piece of info with the function cd which changes the current directory to the one specified, if the change happened successfully, it will return true which then I will capture in my if statement to execute the code, which consists of returning to the original directory (cd ..) and saying to the user it was a directory.
Otherwise, cd will return false and will tell you itself what happened, was it a file or was it nonexistent, and the * (a wildcard) exists to find whatever extension it might have or even doesn't have. I hope this helps, cheers!
There are several ways to classify an entry. For instance,
[[ -f $filename ]]
tests for regular files,
[[ -d $filename ]]
tests for directories, and there are other tests too where you can test for symlinks, or whether you have read/write/execute permissions. You find the list of available file test operators here.
Bash Environment
Given a very simple disk structure as below
And environment path variable set to dir1 and dir2 as below
$ env|grep PATH
returns :-
PATH=/:/usr/bin:/e/path/to/directory/dir1:/e/path/to/directory/dir2
execution of the program fails as below
$ bin/prog.exe
bash: bin/prog1.exe: No such file or directory
or also
$ /bin/prog1.exe
bash: /bin/prog.exe: No such file or directory
however if we modify path to include /bin
PATH=/:/usr/bin:/e/path/to/directory/dir1/bin:/e/path/to/directory/dir2/bin
it does of course work
$ prog1.exe
Hello from prog1 ...
My question is how do I make paths relative to 'environment' PATH work in bash?
In practise I am given some files that have 10's of relative paths generated to many different virtual root locations, to which I cant change.
It is also not possible to use a full path, or just the executable name of (which we know works) for this scenario.
See man bash for explanation (emphasis mine):
If the name is neither a shell function nor a builtin, and contains no slashes, bash searches each element of the PATH for a directory containing an executable file by that name.
There's no such thing as relative path lookup. If your command name contains any / characters, it is treated as a path relative to your current working directory only. If it has no / characters, then the shell will look only in the exact directories, not any subdirectories under them, listed in your PATH.
Relative path lookups would raise a host of issues related to order in which subdirectories should be searched.
As #choroba implies, you can't do what you're asking to do.
If you need to find a program in a subdirectory of one of the entries in your PATH, you'll have to iterate until you find it:
rel_path="bin/prog.exe"
IFS=: read -ra paths <<<"$PATH"
for path in "${paths[#]}"; do
if [[ -x "$path/$rel_path" ]]; then
exe="$path/$rel_path"
break
fi
done
if [[ -z "$exe" ]]; then
echo "cannot find $rel_path"
else
echo "found $rel_path as $exe"
fi
I've just started learning bash yesterday and I need a little help. I need to make a script that will check if a file exists on co-workers computers and, if it doesn't the, script will make one. I have a general idea for that. The more important help I need is recording or logging the script to an output.txt or something of the sorts. I've seen the script command but it seems to be manual. I need it to record every interaction from the start to end and then export it and exit.
I could probably test if that log exists and then append whatever the script needs to check. I assume to start I could do file="./file" (example) and then do
if [ -e "$file" ]; then whatever.
What I plan to do is make a script that maybe checks if a firewall is on or if the co-workers have some file and then export the result(s) to some dir (mkdir). Pure examples. I really just need assistance on the exporting of the whole terminal input and output. Thanks.
This is very simple script just check the existense of file, if so just move it to yourlocaiton dir.
#!/bin/sh
if [ -f /etc/cruelworld.txt ] ; then
echo "File exist and moving it to my dir"
mv /etc/cruelworld.txt /yourlocation
fi
You can write your script as :
if [ -f file.txt ]; then echo "File found"; else touch file.txt; fi
I know I should be able to change the current working directory of a bash script by doing something akin to
cd `dirname $MYPATH`
but for some reason this doesn't work (or not as I imagined it).
#!/bin/bash
WAYPATH="/home/user/articles"
TEST_PATH="/home/user/testing"
# Set working directory of the script to be testing
cd `dirname $TEST_PATH`
for i in $(ls $WAYPATH); do
another_command $i $i.r > $TEST_PATH/htmls/$i.html
done
My goal here is to allow the bash script to find the files located in TEST_PATH (which have matching name to those in WAY_PATH) without having to prefix them with the full path (because another_command) makes use of the whole argument passed to it.
So this is a lesson on understanding what commands do after reading about them on Stackexchange. I was using
cd `dirname $MYPATH`
following this answer where they achieved the desired result
cd `dirname $0`
$0 is the full path of the bash script, so dirname is required to return the path without the name of the file.
Instead, for an arbitrary supplied path is sufficient to do a simple
cd $MYPATH
as suggested in comments.
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