When I manually enter the Windows path in Bash,
I want to convert it to a POSIX path and save it in a variable.
But escape characters are not escaped.
I want to type C:\Users\xiang\Downloads\Compressed and convert it to
/c/users/xiang/downloads/compressed
#!/bin/sh
read -rp "Enter a path: " pth
dir=$(echo "/$pth" | sed -e 's/\\/\//g' -e 's/://')
cd ${dir}
git status
read -n 1 -s -r -p "Press any key to continue"
exit 0;
The problem is that the backslashes in your Windows route are considered as a way to escape a character.
Here you have two options, either you write the route with double backslashes (C:\\Users\\...) or you can use read -rp "Enter a path: " pth (note the r).
Personally I prefer the second option, as you don't have to tell other users to write the route with double backslashes, and is simpler.
It is because bash is considering the backslash \ in your C:\Users\<user>\Downloads\Compressed as an escape character. To solve this issue you need to give the input as C:\\Users\\<user>\\Downloads\\Compressed.
I'm new to shell script, so one of the first things to learn is something like:
echo "Hello there"
However, this returns:
"Hello there"
The shell seems to interpret quotes as part of the string.
This is not limited to the echo command, but also, for example: printf or read.
These are not equivalent: ¨ and ". In the shell, use " (34, \x22) for double quotes, not “ or ” etc.
Here below is the applescript:
do script ("aria2c -i /Users/mac/Downloads/aria2c\ \(1\).down") in currentTab
The expected result in shell would like this:
~$ aria2c -i /Users/mac/Downloads/aria2c\ \(1\).down
But it doesn't work...
In AppleScript a backslash must be escaped with a second one:
do script ("aria2c -i /Users/mac/Downloads/aria2c\\ \\(1\\).down") in currentTab
A smarter way is quoted form of, it magically adds all necessary backslashes / quotation characters
do script "aria2c -i " & quoted form of "/Users/mac/Downloads/aria2c (1).down" in currentTab
What I want to achieve: I input s in the terminal, and after 25 minutes I get a notification to take a break. Here is the code:
alias s='sleep 1500 && osascript -e 'display notification "break" with title "break"''
I get an error if I include the final ', and also if I don't.
Using an alias
One can combine single-quoted strings with single quotes as follows:
$ echo 'a'\''b'
a'b
In the above, 'a' is a single-quoted string. It is followed by an escaped single-quote \' which is followed by another single-quoted string 'b'. In this way, one can build complex strings with single-quotes.
For your command, that would look like:
alias s='sleep 1500 && osascript -e '\''display notification "break" with title "break"'\'
Using a function
As #Kevin pointed out, this is simpler:
unalias s
s() { sleep 1500 && osascript -e 'display notification "break" with title "break"'; }
I am by no means an AppleScript expert, but get by. I am running into a hell of a time trying to pass some AppleScript variables to a sed command in order to replace some text in a file, based on the variables.
I have two dialog boxes in AppleScript that grab user data, and I store those variables. myData - This works OK.
set myData to text returned of ¬
(display dialog "Enter Your Data" with title ¬
"Data Entry" default answer ¬
"" buttons {"Continue…"} ¬
default button 1 ¬
)
set searchFor to quoted form of "data1"
set searchFor2 to quoted form of "data2"
set inputFile to "/Users/User1/Desktop/file.txt"
set outputFile to "/Users/User1/Desktop/file1.txt"
do shell script quoted form of ("sed -i.bak s/" & searchFor & "/" & myData & "/g") & " " & inputFile & " > " & outputFile
I actually get this error: No such file or directory, exit code 127. The weird part is, though, that it does write out the file with zero data in it. I am not necessarily trying to write out a diff file as the script suggests, just edit data in place. However, I've had zero success that way, which is why I approached it this way.
Any assistance with my issue would be greatly appreciated!
Your immediate issues are that you mistakenly apply quoted form of multiple times, and, more to the point, apply quoted form of to the sed executable name, its options, and the sed script together, which invariably breaks (see below for a detailed explanation); try the following - without applying quoted form of to any of the variables beforehand - note how quoted form of is applied selectively to the sed script and the in- and output files, respectively:
do shell script "sed " & quoted form of ¬
("s/" & searchFor & "/" & myData & "/g") ¬
& " " & quoted form of inputFile & " > " & quoted form of outputFile
Note that I've removed -i.bak from your command, because it would invariably result in an empty output file: -i updates the input file in place, producing no stdout output. Thus, nothing would be sent to outputFile with > outputFile.
However, this can still break or misbehave, if searchFor and myData contain either / or characters that have special meaning in a sed regular expression (e.g., \, *, [, ...) or replacement string (e.g., &, \).
To avoid that, you'll have to escape the input strings first, which is non-trivial, unfortunately.
The following handlers provide robust, generic escaping - they are based on this answer, where the underlying commands are explained[1]) :
# Quotes (escapes) a string for safe use in a `sed` regex.
on quoteRegex(txt)
do shell script "sed -e 's/[^^]/[&]/g; s/\\^/\\\\^/g; $!a\\'$'\\n''\\\\n' <<<" & quoted form of txt & " | tr -d '\\n'"
end quoteRegex
# Quotes (escapes) a string for safe use in a `sed` substitution string (`s///` function).
on quoteSubst(txt)
do shell script "IFS= read -d '' -r <<<\"$(sed -e ':a' -e '$!{N;ba' -e '}' -e 's/[&/\\]/\\\\&/g; s/\\n/\\\\&/g' <<<" & quoted form of txt & "; printf X)\"; printf %s \"${REPLY%$'\\n'X$'\\n'}\"" without altering line endings
end quoteSubst
[1] Some tweaks were necessary to make them work with do shell script; notably, process substitution (<(...)) is not supported; the workaround via <<<"$(...)" necessitated extra steps to accurately preserve trailing newlines in the input.
Once you've pasted above handlers into your script, here's how to apply them to your command:
do shell script "sed " & quoted form of ¬
("s/" & my quoteRegex(searchFor) & "/" & my quoteSubst(myData) & "/g") ¬
& " " & quoted form of inputFile & " > " & quoted form of outputFile
As for you original symptoms:
The weird part is, though, that it does write out the file with zero data in it.
This indicates that do shell script (a) was able to invoke the shell, (b) the shell parsed the command line without encountering a syntax error; if these conditions are met, an output redirection such as > outFile causes the target file to created as a zero-byte file, or, if it existed, to truncate it to a zero-byte file, BEFORE command execution begins.
If command execution then fails, the zero-byte file is left behind.
I actually get this error: No such file or directory, exit code 127
Exit code 127 indicates that the executable that is the 1st token of your command string could not be invoked, because it could not be found.
This is indeed what happened, because you mistakenly applied quoted form of to the sed executable name, its options, and the sed script together, which causes the entire resulting string to be interpreted as the executable name, which obviously fails.
Let's take a simplified example:
quoted form of "sed s/foo/bar/g file"
yields 'sed s/foo/bar/g file', including the enclosing single quotes.
Passing this string to the shell causes the shell to consider this string a single token that constitutes the executable path or filename. Obviously, no file named sed s/foo/bar/g file exists, so the command fails.
The solution, as demonstrated above, is to pass sed, its options, the script, as well as the input filename and the output filename as separate tokens.