shell script capture variable without formatting escape characters - shell

I am running an .sh script from wsl bash.
Inside the script I want capture a file path, into a variable, in order to pass it to cmd.exe like so:
my_win_path=<some_windows_unc_path_to_executable>
cmd.exe /c "$my_win_path"
However when I try to capture the file path, it's backslashes are getting formatted, resulting in an non-valid path.
Example:
~: wslpath -w .
C:\tmp
~: var=$(wslpath -w .); echo $var
C: mp
cmd.exe /c "$var # will error
How do I capture the output of wslpath into a valid variable without formatting the escape characters ?
(I hope I am using the right terminology here. Please correct me if not.)

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.

ubuntu 20.04 7z command on bash script

I'm using this script to shortcut a 7z command with prefered options:
#!/bin/bash
7z a -t7z -m0=lzma2 -mx=9 -ms=on -mmt=on "$1".7z $2
If I give it a folder as the second argument it work just fine, but if I send something like *file*.png, it creates the 7z files but there is nothing on it... What I'm doing wrong?
When pressing [Enter] key after writing the script name and its parameters in the terminal, the current bash is expanding the *file*.png: it is replaced by the list of the files found on the disk, and then the script is run.
So, $2 is the first file from the list of the files found by the shell after *file.*.png was expanded: see PARAMETERS and Special Parameters and pathname expansion in the man bash.
As wrote in the comment, a quick win, using the same script, unchanged, is to prevent the pathname expansion using 2 ' chars in the command line:
$ my-7z.sh png-files '*file*.png'
The definitive solution, is to handle the positional parameters:
#!/bin/bash
7z_filename="${1}".7z
shift
7z a -t7z -m0=lzma2 -mx=9 -ms=on -mmt=on "${7z_filename}" "${#}"
Maybe it is worth to check the positional parameters, to add some error management.

How to escape quotation marks in WinDbg's startup command line opening a dump

Following this answer, I'm trying to set up a .dmp shell command in the Registry using the -c "..." switch to execute commands whenever I open a dump file.
While this works for any commands not using quotation marks, I'd now like to use a command which needs quotation marks. How can I escape the quotation marks to that they are not seen as the end of the -c "..." switch?
I tried:
escaping with a backslash \"
escaping by doubling the quotation marks ""
Details are :
Registry key: HKEY_CLASSES_ROOT\Windbg.DumpFile.1\shell\WinDbgStartup\command
(Default) value (working): "C:\path to\windbg.exe" -z "%1" -Q -c ".echo Welcome"
(Default) value (broken): "C:\path to\windbg.exe" -z "%1" -Q -c ".echo Wel""come"
-z is for opening a dump file, -Q is for quiet workspaces, at -c I can enter commands and I want to include quatation marks.
Error message: The command line arguments cannot specify more than one kind of debugging to start
WinDbg Version: 6.2.9200.16384 X86
Have you tried ^" ? ^ escapes most characters in cmd
(On investigation)
Quote fromWinDbg Command-Line Options
-c " command "
Specifies the initial debugger command to run at start-up. This command must be
enclosed in quotation marks. Multiple commands can be separated with semicolons.
(If you have a long command list, it may be easier to put them in a script and
then use the -c option with the $<, $><, $><, $$>< (Run Script File) command.)
If you are starting a debugging client, this command must be intended for the
debugging server. Client-specific commands, such as .lsrcpath, are not allowed.
And clicking on the $... hyperlink further explains these options.
Seems that you actually want to include the " in your echo. Frankly, I've no idea - but what I'd try would be -c ".echo Wel^"come"
and if that doesn't work, I'd go off to the $-option gobbledegook. No-one (sane) ever claimed that every possibility had been considered in constructing these facilities...

How to use Windows environment variables in Vim script?

I have a Vim script that calls an external shell script and reads the output into the current buffer. It works fine in Unix systems. I'm trying to make the script OS-agnostic, so I want it to work for Windows users too. Here's the relevant line from the script:
:exe ":0r !$HOME/bin/shell_script"
According to Vim's docs, $HOME should translate fine for Windows users too. Using gvim on Win XP in command mode, doing
:echo $HOME
does indeed produce "C:\Documents and Settings\my_user".
However, my Vim script (adjusted for backslashes) fails on the Windows machine with a message in the DOS cmd.exe window saying
$HOME\bin\shell_script" not found.
In other words, Vim appears not to be expanding the value of $HOME before passing it to cmd.exe.
I can't use %APPDATA% either because Vim interprets % as the current file and pre/appends the file name to APPDATA. Weird that Vim does expand % but doesn't expand $HOME.
How do I get $HOME expanded correctly? Is it because I'm using exe in the vim script?
You don't need ! to read a file.
:exe ":0r $HOME/bin/shell_script"
Or read type command in windows(like cat in linux):
:exe '0r !type "'. $HOME . '\bin\shell_script"'
Note:
the type is executed in windows shell, so you need \(backslash) in path
if $HOME contains spaces, you need "(double-quote) to preserves the literal value of spaces
To clarify the answer given by kev:
On windows the $HOME variable do not expand properly when you escape to the console. For example, consider this code:
:e $HOME/myscript
This works because vim expands $HOME as normal. On the other hand this won't work:
:%! $HOME/myscript
Why? Because vim passes everything after ! to the underlying shell, which on Windows is cmd.exe which does environment variables %LIKE_THIS%. If you try to use that notation, vim will jump in and expand % to the name of the current file - go figure.
How to get around it? Use exe keyword:
:exe "%! ".$HOME."\myscript"
Let's analyze:
:exe is a command that takes a string and evaluates it (think eval in most languages)
"!% " the escape to shell command. Note that it is quoted so that exe can evaluate it. Also note how there is an extra space there so that when we append the home var it does not but right against it
.$HOME the dot is a string concatenation symbol. The $HOME is outside of the quotes but concatenated so that vim can expand it properly
."/myscript" path to script and possible arguments (also quoted)
The important thing here is keeping $HOME outside of the quote marks, otherwise it may not be properly expanded on Windows.
You probably need something like the expand function. For example:
:echo expand("$HOME/hello")
/home/amir/hello
You can find out more info about expand() with :help expand.
Here you have some information about slashes and backslashes in vim:
http://vimdoc.sourceforge.net/htmldoc/os_dos.html
When you prefer to use forward slashes, set the 'shellslash' option.
Vim will then replace backslashes with forward slashes when expanding
file names. This is especially useful when using a Unix-like 'shell'.

command substitution but without breaking output into multiple arguments

Is there a way to do command substitution in BASH shell without breaking output into multiple arguments?
I copy the path of some directory (from the location bar in a GUI file browser) to clipboard and then issue the following command, where the command xsel returns the clipboard content, which is the path of the directory in this case:
cd `xsel`
But some path contain spaces or may even contain some special characters used by BASH.
How can I pass the output of a command as a single argument and without BASH messing with special characters?
cd "$(xsel)"
seems to handle all special characters (including $ and spaces).
My test string was boo*;cd.*($\: $_
$ mkdir "$(xsel)"
$ ls
boo*;cd.*($\: $_
$ file boo\*\;cd.\*\(\$\\\:\ \$_/
boo*;cd.*($\: $_/: directory
$ cd "$(xsel)"
$ pwd
/tmp/boo*;cd.*($\: $_
Have you tried:
cd "`xsel`"
That should do the job, unless you have dollars($) or back-slashes (\) in your path.
If you aren't doing this programmatically, most terminals in Linux let you paste from the clipboard with a middle-click on your mouse. Of course, you'll still need to put quotes before and after your paste, like #dave suggests.

Resources