How to use paths with spaces in automator shell script? - automator

I have an Automator workflow which should set the CreationDate of the selected file to a date which I want to enter. Unfortunately my path have spaces. Therefore it doesn'w work.
I've tried several variants like:
SetFile -d \"$1 12:00:00\" "$#2"
SetFile -d \"$1 12:00:00\" \"$#2\"
SetFile -d \"$1 12:00:00\" '$#2'
SetFile -d \"$1 12:00:00\" \'$#2\'
The path is like follows:
/Users/simon/Documents/Steuern/Steuern 2021/Scan_000775.pdf
The shell I use is ZSH with oh-my-zsh installed.
This is the Workflow I have:
Ask for Finder-Object
Get value of variable
Ask for Text input
Set value of variable
Ask for value of variable
execute shell script: "SetFile -d "$1 12:00:00" "$#2""
Can anyone tell me how to write the shellscript to use pathnames with spaces?
That would be very nice. Thank you.

If I'm understanding right, you want:
SetFile -d "$1 12:00:00" "${#:2}"
Explanation: escaping quotes prevents them from acting like quotes (it turns them into normal characters); in this case, you want them to function as quotes, so you shouldn't escape them. Also, "$#2" doesn't get the arguments starting at $2, it gets all of the arguments, and sticks a "2" to the end of the last one. If you want all the arguments except the first, use "${#:2}" instead.

Related

SQLCMD failure executing stored procedure with parameter

New to using SQLCMD.
If I run the following sqlcmd I get an error
Incorrect syntax near '.209
Command:
sqlcmd -E -S MyServer\SQLEXPRESS -d MyDatebase-Q "EXEC spRunThisPS #IP=$(IP)" /v IP="192.168.209.4"
If I just have "192.168" as the parameter the script will run (obviously the PS fails because invalid ip). Not sure if the amount of "." causes it to fail or not.
Any thoughts or suggestions?
Nick
You probably need to wrap the parameter value in quotes, either by specifying the IP value as IP="'192.168.209.4'", or by adding them around the parameter value in the EXEC command (EXEC spRunThisPS #IP='$(IP)').
Otherwise it's trying to interpret it as a numeric value rather than a string, which is why 192.168 is ok and 192.168.209.4 isn't.

How to escape Jenkins parameterized build variables

I use Jenkins ver. 1.522 and I want to pass a long string with spaces and quotes as a parameter in the parameterized build section. The job only runs a python script.
My problem is that I can't find a way to escape my string so that jenkins passes it correctly to the script.
Assuming...
string: fixVersion in ("foo") AND issuetype in (Bug, Improvement) AND resolution = Fixed ORDER BY resolution ASC, assignee ASC, key DESC
variable name: bar
script name: coco.py
When I run the script in the terminal, everything is fine: python coco.py --option 'fixVersion in ("foo") AND issuetype in (Bug, Improvement) AND resolution = Fixed ORDER BY resolution ASC, assignee ASC, key DESC'
When I run the same script with jenkins using the parametrized build and try to escape the variable so it end up taken as one parameter by the py script it is oddly espacped by jenkins.
In my jenkins job I call the script: python coco.py --option \'${BAR}\'
and it ends up as:
python coco.py --option '"fixVersion' in '('\''foo'\'')' AND issuetype in '(Bug,' 'Improvement)' in '(Production,' 'Stage)' AND resolution = Fixed ORDER BY resolution ASC, assignee ASC, key 'DESC"'
I also tried \"${BAR}\", \"$BAR\",\'$BAR\'
What it the right way do acheive it?
Try
python coco.py --option "${BAR}"
Alternatively, if you need the single quotes surrounding everything
python coco.py --option \'"${BAR}"\'
In the cases you listed, bash will treat the spaces as delimiters. Putting the double quotes around a variable will preserve the whitespace in a string. Example
aString='foo bar'
for x in $aString; do echo $x; done
# foo
# bar
for x in "$aString"; do echo $x; done
# foo bar
I am using Jenkins v1.606 and ran into this same issue!
The issue that I saw passing user defined string params containing spaces into an execution shell would not properly format the string (only with a parameter that had 1 or more spaces). What you have to watch out for is reviewing the 'output' log. Jenkins will not properly display the string param value within the log.
Example (correct format for containing spaces):
docker exec -i container-base /bin/bash -c "cd /container/path/to/code/ && ./gradlew test_xml -P DISPLAY_NAME='${DISPLAY_NAME}' -P USERNAME='${USERNAME}' -P SERVER_NAME='${SERVER_NAME}'"
Jenkins Output of string (notice the string values format):
+ docker exec -i container-base /bin/bash -c 'cd /container/path/to/code/ && ./gradlew test_xml -P DISPLAY_NAME='\''VM10 USER D33PZ3R0'\'' -P USERNAME='\''d33pz3r0#stackoverflow.com'\'' -P SERVER_NAME='\''stackoverflow.com'\'''
Conclusion:
In my example, the literal command was encapsulated with <">, followed by surrounding the parameters with <'> to escape the literal cmd string and control the Jenkins string syntax. Remember not to just watch your Jenkins output log as it lead me wrong for an entire day while I fought with this! This should be the same for your issue as well, you do not need to escape with \' or other escape characters. Hope this helps!!

How can I tell from a within a shell script if the shell that invoked it is an interactive shell?

I'm trying to set up a shell script that will start a screen session (or rejoin an existing one) only if it is invoked from an interactive shell. The solution I have seen is to check if $- contains the letter "i":
#!/bin/sh -e
echo "Testing interactivity..."
echo 'Current value of $- = '"$-"
if [ `echo \$- | grep -qs i` ]; then
echo interactive;
else
echo noninteractive;
fi
However, this fails, because the script is run by a new noninteractive shell, invoked as a result of the #!/bin/sh at the top. If I source the script instead of running it, it works as desired, but that's an ugly hack. I'd rather have it work when I run it.
So how can I test for interactivity within a script?
Give this a try and see if it does what you're looking for:
#!/bin/sh
if [ $_ != $0 ]
then
echo interactive;
else
echo noninteractive;
fi
The underscore ($_) expands to the absolute pathname used to invoke the script. The zero ($0) expands to the name of the script. If they're different then the script was invoked from an interactive shell. In Bash, subsequent expansion of $_ gives the expanded argument to the previous command (it might be a good idea to save the value of $_ in another variable in order to preserve it).
From man bash:
0 Expands to the name of the shell or shell script. This is set
at shell initialization. If bash is invoked with a file of com‐
mands, $0 is set to the name of that file. If bash is started
with the -c option, then $0 is set to the first argument after
the string to be executed, if one is present. Otherwise, it is
set to the file name used to invoke bash, as given by argument
zero.
_ At shell startup, set to the absolute pathname used to invoke
the shell or shell script being executed as passed in the envi‐
ronment or argument list. Subsequently, expands to the last
argument to the previous command, after expansion. Also set to
the full pathname used to invoke each command executed and
placed in the environment exported to that command. When check‐
ing mail, this parameter holds the name of the mail file cur‐
rently being checked.
$_ may not work in every POSIX compatible sh, although it probably works in must.
$PS1 will only be set if the shell is interactive. So this should work:
if [ -z "$PS1" ]; then
echo noninteractive
else
echo interactive
fi
try tty
if tty 2>&1 |grep not ; then echo "Not a tty"; else echo "a tty"; fi
man tty :
The tty utility writes the name of the terminal attached to standard
input to standard output. The name that is written is the string
returned by ttyname(3). If the standard input is not a terminal, the
message ``not a tty'' is written.
You could try using something like...
if [[ -t 0 ]]
then
echo "Interactive...say something!"
read line
echo $line
else
echo "Not Interactive"
fi
The "-t" switch in the test field checks if the file descriptor given matches a terminal (you could also do this to stop the program if the output was going to be printed to a terminal, for example). Here it checks if the standard in of the program matches a terminal.
Simple answer: don't run those commands inside ` ` or [ ].
There is no need for either of those constructs here.
Obviously I can't be sure what you expected
[ `echo \$- | grep -qs i` ]
to be testing, but I don't think it's testing what you think it's testing.
That code will do the following:
Run echo \$- | grep -qs i inside a subshell (due to the ` `).
Capture the subshell's standard output.
Replace the original ` ` expression with a string containing that output.
Pass that string as an argument to the [ command or built-in (depending on your shell).
Produce a successful return code from [ only if that string was nonempty (assuming the string didn't look like an option to [).
Some possible problems:
The -qs options to grep should cause it to produce no output, so I'd expect [ to be testing an empty string regardless of what $- looks like.
It's also possible that the backslash is escaping the dollar sign and causing a literal 'dollar minus' (rather than the contents of a variable) to be sent to grep.
On the other hand, if you removed the [ and backticks and instead said
if echo "$-" | grep -qs i ; then
then:
your current shell would expand "$-" with the value you want to test,
echo ... | would send that to grep on its standard input,
grep would return a successful return code when that input contained the letter i,
grep would print no output, due to the -qs flags, and
the if statement would use grep's return code to decide which branch to take.
Also:
no backticks would replace any commands with the output produced when they were run, and
no [ command would try to replace the return code of grep with some return code that it had tried to reconstruct by itself from the output produced by grep.
For more on how to use the if command, see this section of the excellent BashGuide.
If you want to test the value of $- without forking an external process (e.g. grep) then you can use the following technique:
if [ "${-%i*}" != "$-" ]
then
echo Interactive shell
else
echo Not an interactive shell
fi
This deletes any match for i* from the value of $- then checks to see if this made any difference.
(The ${parameter/from/to} construct (e.g. [ "${-//[!i]/}" = "i" ] is true iff interactive) can be used in Bash scripts but is not present in Dash, which is /bin/sh on Debian and Ubuntu systems.)

how to invoke java.exe in bash under windows in cygwin with space in path

I tried to invoke java inside bash script on windows (Win XP) using cygwin.
However path to java.exe contain spaces.
only literaly putting in bash sometghing like this worked:
/cygdrive/c/Program\ Files/Java/jdk1.5.0_10/bin/java -cp "$TOOL_HOME" DateParse "$DATE" "$FORMAT"
My attemts to put java path to a variable failed:
export JAVA_EXE="/cygdrive/c/Program\ Files/Java/jdk1.5.0_10/bin/java"
$JAVA_EXE -cp "$TOOL_HOME" DateParse "$DATE" "$FORMAT"
also different combination with cygpath, quotes, brackets did not work. I am not finding the the right combination
Put quotes around $JAVA_EXE:
"$JAVA_EXE" -cp "$TOOL_HOME" DateParse "$DATE" "$FORMAT"
The problem is that every time a variable is expanded, its also broken into words at spaces, UNLESS you put quotes around it. So if you don't want things broken at spaces, you need quotes.
Another alternative is to always use short (DOS) names for things, which don't allow spaces. To see what the short name is, run
cygpath -d "$JAVA_EXE"
to convert that back to a unix-like cygwin path, use
cygpath -u $(cygpath -d "$JAVA_EXE")
thank you for your ideas. It worked in proper combination. The issue was that I was escaping space character and at the same time putting JAVA_EXE in quotes.
export JAVA_EXE="/cygdrive/c/Program Files/Java/jdk1.5.0_10/bin/java"
"$JAVA_EXE" -cp "$TOOL_HOME" DateParse "$DATE" "$FORMAT"
produce this effect:
line 30: /cygdrive/c/Program\ Files/Java/jdk1.5.0_10/bin/java: No such file or directory
on the other hand, converting to DOS 8.3 does not work neither:
cannot create short name of \\?\C:\Program\ Files\Java\jdk1.5.0_10
\bin\java
Finally, putting JAVA_EXE in quotes but without escaping space in path worked fine for me:
export JAVA_EXE="/cygdrive/c/Program Files/Java/jdk1.5.0_10/bin/java"
"$JAVA_EXE" -cp "$TOOL_HOME" DateParse "$DATE" "$FORMAT"

unix at command pass variable to shell script?

I'm trying to setup a simple timer that gets started from a Rails Application. This timer should wait out its duration and then start a shell script that will start up ./script/runner and complete the initial request. I need script/runner because I need access to ActiveRecord.
Here's my test lines in Rails
output = `at #{(Time.now + 60).strftime("%H:%M")} < #{Rails.root}/lib/parking_timer.sh STRING_VARIABLE`
return render :text => output
Then my parking_timer.sh looks like this
#!/bin/sh
~/PATH_TO_APP/script/runner -e development ~/PATH_TO_APP/lib/ParkingTimer.rb $1
echo "All Done"
Finally, ParkingTimer.rb reads the passed variable with
ARGV.each do|a|
puts "Argument: #{a}"
end
The problem is that the Unix command "at" doesn't seem to like variables and only wants to deal with filenames. I either get one of two errors depending on how I position "s
If I put quotes around the right hand side like so
... "~/PATH_TO_APP/lib/parking_timer.sh STRING_VARIABLE"
I get,
-bash: ~/PATH_TO_APP/lib/parking_timer.sh STRING_VARIABLE: No such file or directory
I I leave the quotes out, I get,
at: garbled time
This is all happening on a Mac OS 10.6 box running Rails 2.3 & Ruby 1.8.6
I've already messed around w/ BackgrounDrb, and decided its a total PITA. I need to be able to cancel the job at any time before it is due.
After playing around with irb a bit, here's what I found.
The backtick operator invokes the shell after ruby has done any interpretation necessary. For my test case, the strace output looked something like this:
execve("/bin/sh", ["sh", "-c", "echo at 12:57 < /etc/fstab"], [/* 67 vars */]) = 0
Since we know what it's doing, let's take a look at how your command will be executed:
/bin/sh -c "at 12:57 < RAILS_ROOT/lib/parking_timer.sh STRING_VARIABLE"
That looks very odd. Do you really want to pipe parking_timer.sh, the script, as input into the at command?
What you probably ultimately want is something like this:
/bin/sh -c "RAILS_ROOT/lib/parking_timer.sh STRING_VARIABLE | at 12:57"
Thus, the output of the parking_timer.sh command will become the input to the at command.
So, try the following:
output = `#{Rails.root}/lib/parking_timer.sh STRING_VARIABLE | at #{(Time.now + 60).strftime("%H:%M")}`
return render :text => output
You can always use strace or truss to see what's happening. For example:
strace -o strace.out -f -ff -p $IRB_PID
Then grep '^exec' strace.out* to see where the command is being executed.

Resources