Why does zsh interpret $HOME:abc like /userbc? bash interprets it as /user:abc.
zsh
$echo $HOME:abc
/userbc
bash
$echo $HOME:abc
/user:abc
History expansion, filename generation and parameter expansion all have modifiers of the form :N after the expansion. :a means to expand to an absolute path. Use ${HOME}:abc instead to treat the colon as a literal character.
You are using zsh modifiers, of which “a” is a valid one.
echo ${HOME}:abc
/root:abc
Avoid in zsh by using {}.
Related
I need a solution in zsh
I have a string like http://xxx.abc.mp3?yyy:mno. Is there a one-liner in zsh that can extract the string until mp3, that http://xxx.abc.mp3? I can do this in bash, but I needed a way to do it in zsh.
You didn't say how you did it in bash, but the same substitution works with both shells:
str='http://xxx.abc.mp3?yyy:mno'
printf "%s\n" "${str/%\?*}"
Removes the text that matches a question mark and 0 or more characters until the end of the string.
I have a simple shell function to convert a *nix style path to Windows style (I happen to be using Windows Subsystem for Linux).
# convert "/mnt/c/Users/josh" to "C:\Users\josh"
function winpath(){
enteredPath=$1
newPath="${enteredPath/\/mnt\/c/C:}" # replace /mount/c/ with C:
newPath="${newPath//\//\\}" # replace / with \
echo $newPath
}
The desired behavior is:
$ winpath /mnt/c/Users/josh
C:\Users\josh
This works correctly in bash, but in zsh, echo seems to do some extra interpolation of the $newPath value. It behaves like this:
$ winpath /mnt/c/Users/josh
C:sers\josh
What character sequence is echo interpolating and why is it remove the \U? Most importantly, how do I return the literal value?
I've tried digging through the zsh documentation, but it's a jungle. Thanks in advance!
zsh processes certain escape sequences that bash does not by default. \U introduces 4-byte Unicode codepoint, but since the following 8 characters are not a valid hexadecimal number, no character is substituted.
I would recommend using printf, as its behavior is much more predictable from shell to shell.
printf '%s\n' "$newPath"
The problem is that you are using the internal command echo, instead of the external one. If you would write
command echo $newPath
you would get the expected output. command forces zsh to look up the command word according to the current PATH, ignoring internal commands, aliases or functions of the same name.
I am trying to port this snippet of code from bash to zsh:
#! /usr/bin/env bash # change zsh
set -x
pattern="[ab]"
marks="a"
case "${marks}" in
${pattern})
echo match
;;
esac
This prints "match".
Bash replaces ${pattern} as is and then uses [ab] to match either 'a' or 'b'.
zsh seemingly escapes the '[]' characters and then uses \[ab\] to match this string verbatim.
I don't see a zsh option, how to change the behavior and hardcoding the pattern is not an option.
To make zsh treat a parameter value as a pattern, instead of a literal string, you need to use glob substitution:
local marks=a pattern='[ab]'
case $marks in
( $~pattern )
echo match
;;
esac
The parameter passed is changed when printed from inside the function
print "param: $FILEPREFIX" 1>&2; #return finyear*
func_copy $FILEPREFIX
then in function
function func_copy
{
fp=$1
print "param: $fp" 1>&2; #returns finyear.scr which is a script file name
what would i be doing wrong here
When you invoke func_copy $FILEPREFIX and FILEPREFIX contains finyear*, the shell expands the variable and then does wild-card matching, so the name finyear* is changed to finyear.scr in your directory. To avoid the expansion, enclose the name in double quotes:
func_copy "$FILEPREFIX"
(Using double quotes around a variable expansion is usually, but not always, a good idea.)
See the Bash manual on shell expansions for the sequence of operations in Bash. The POSIX shell (sh) has similar rules, and Korn shell will likewise be similar — they all have a common ancestor, the Bourne shell.
How does unix handle full path name with space and arguments ?
In windows we quote the path and add the command-line arguments after, how is it in unix?
"c:\foo folder with space\foo.exe" -help
update:
I meant how do I recognize a path from the command line arguments.
You can either quote it like your Windows example above, or escape the spaces with backslashes:
"/foo folder with space/foo" --help
/foo\ folder\ with\ space/foo --help
You can quote if you like, or you can escape the spaces with a preceding \, but most UNIX paths (Mac OS X aside) don't have spaces in them.
/Applications/Image\ Capture.app/Contents/MacOS/Image\ Capture
"/Applications/Image Capture.app/Contents/MacOS/Image Capture"
/Applications/"Image Capture.app"/Contents/MacOS/"Image Capture"
All refer to the same executable under Mac OS X.
I'm not sure what you mean about recognizing a path - if any of the above paths are passed as a parameter to a program the shell will put the entire string in one variable - you don't have to parse multiple arguments to get the entire path.
Since spaces are used to separate command line arguments, they have to be escaped from the shell. This can be done with either a backslash () or quotes:
"/path/with/spaces in it/to/a/file"
somecommand -spaced\ option
somecommand "-spaced option"
somecommand '-spaced option'
This is assuming you're running from a shell. If you're writing code, you can usually pass the arguments directly, avoiding the problem:
Example in perl. Instead of doing:
print("code sample");system("somecommand -spaced option");
you can do
print("code sample");system("somecommand", "-spaced option");
Since when you pass the system() call a list, it doesn't break arguments on spaces like it does with a single argument call.
Also be careful with double-quotes -- on the Unix shell this expands variables. Some are obvious (like $foo and \t) but some are not (like !foo).
For safety, use single-quotes!
You can quote the entire path as in windows or you can escape the spaces like in:
/foo\ folder\ with\ space/foo.sh -help
Both ways will work!
I would also like to point out that in case you are using command line arguments as part of a shell script (.sh file), then within the script, you would need to enclose the argument in quotes. So if your command looks like
>scriptName.sh arg1 arg2
And arg1 is your path that has spaces, then within the shell script, you would need to refer to it as "$arg1" instead of $arg1
Here are the details
If the normal ways don't work, trying substituting spaces with %20.
This worked for me when dealing with SSH and other domain-style commands like auto_smb.