How to deal with colons ":" in filename in shell script - macos

I have a large group of files with ":" in their file names. When I'm in the interactive shell, typing "\" and then hitting tab does the trick to get them recognized as valid inputs to commands, but not so in the shell script.
I've tried
less file:name.txt
less file\:name.txt
less 'file\:name.txt
less 'file:name.txt'
and it's not recognized as a valid file.
However on the interactive command line I type less, followed by first file, then I type \, and then hit the TAB key, everything then works...
How do I do this in the shell script?

Use double quotes:
less "file:name.txt"
Bash recognizes the value within the double quotes as a full string.
As seen in Using quotes to include spaces and characters in filenames:
If you want to work with files with spaces or special characters in
the filename, you may have to use quotes.

This is working even when you don't put anything.
you can try:
less file and it recognizes it for you...
But you can use less "file:name.txt" as string in your bash.

Related

How to read arguments with ampersand in bash [duplicate]

I'm building a shell script (trying to be POSIX compliant) and I'm stuck in an issue.
The script is supposed to receive an URL and do some things with it's content.
myscript www.pudim.com.br/?&args=ok
The thing is, the ampersand symbol is interpreted as a command additive, and giving to my script only the www.pudim.com.br/? part as an argument.
I know that the right workaround would be to surround the URL with quotes but, because I need to use this script several times in a row, I wanted to paste the URL's without having to embrace it with quotes every time.
Is there some way to get the full URL argument, somehow bypassing the ampersand?
Quotes for full URL
Wrapping the URL in quotes will be your only chance. See popular shell utility curl, as it states for its core argument URL:
When using [] or {} sequences when invoked from a command line prompt,
you probably have to put the full URL within double quotes to avoid
the shell from interfering with it. This also goes for other
characters treated special, like for example '&', '?' and '*'.
See also this question and that.
Extra argument(s) for specifying query parameters
You can also pass query parameter (key-value pair) as separate argument. So you can bypass & as separator. See curl's -F option:
-F, --form <name=content>
Read URL from STDIN
If your script allows user interaction you could read the unescaped URL (including metachars as &) from an uninterpreted input-source. See this tutorial.
You can escape just the ampersand; quotes effectively escape every character between them.
myscript www.pudim.com.br/\?\&args=ok # The ? should be escaped as well
There is no solution that lets you avoid all quoting, as & is a shell metacharacter whose unquoted meaning cannot be disabled. The & terminates the preceding command, causing it to be run in a background process; adding some redundant whitespace, you attempt is the same as
myscript www.pudim.com.br/? &
args=ok
Unescaped, the ? will cause the URL to be treated as a pattern to expand. However, it's unlikely the pattern will match any existing file, and bash's default behavior is to treat an unmatched pattern literally. (The failglob option will treat it as an error, and the nullglob option will make the URL disappear completely from the command line, but neither option is enabled by default.)

How to use a pure string as an argument for python program through bash terminal

I am trying to give an argument to my python program through the terminal.
For this I am using the lines:
import sys
something = sys.argv[1]
I now try to put in a string like this through the bash terminal:
python my_script.py 2m+{N7HiwH3[>!"4y?t9*y#;/$Ar3wF9+k$[3hK/WA=aMzF°L0PaZTM]t*P|I_AKAqIb0O4# cm=sl)WWYwEg10DDv%k/"c{LrS)oVd§4>8bs:;9u$ *W_SGk3CXe7hZMm$nXyhAuHDi-q+ug5+%ioou.,IhC]-_O§V]^,2q:VBVyTTD6'aNw9:oan(s2SzV
This returns a bash error because some of the characters in the string are bash special characters.
How can I use the string exactly as it is?
You can put the raw string into a file, for example like this, with cat and a here document.
cat <<'EOF' > file.txt
2m+{N7HiwH3[>!"4y?t9*y#;/$Ar3wF9+k$[3hK/WA=aMzF°L0PaZTM]t*P|I_AKAqIb0O4# cm=sl)WWYwEg10DDv%k/"c{LrS)oVd§4>8bs:;9u$ *W_SGk3CXe7hZMm$nXyhAuHDi-q+ug5+%ioou.,IhC]-_O§V]^,2q:VBVyTTD6'aNw9:oan(s2SzV
EOF
and then run
python my_script.py "$(< file.txt)"
You can also use the text editor of your choice for the first step if you prefer that.
If this is a reoccurring task, which you have to perform from time to time, you can make your life easier with a little alias in your shell:
alias escape='read -r string ; printf "Copy this:\n%q\n" "${string}"'
It is using printf "%q" to escape your input string.
Run it like this:
escape
2m+{N7HiwH3[>!"4y?t9*y#;/$Ar3wF9+k$[3hK/WA=aMzF°L0PaZTM]t*P|I_AKAqIb0O4# cm=sl)WWYwEg10DDv%k/"c{LrS)oVd§4>8bs:;9u$ *W_SGk3CXe7hZMm$nXyhAuHDi-q+ug5+%ioou.,IhC]-_O§V]^,2q:VBVyTTD6'aNw9:oan(s2SzV
Copy this:
2m+\{N7HiwH3\[\>\!\"4y\?t9\*y#\;/\$Ar3wF9+k\$\[3hK/WA=aMzF°L0PaZTM\]t\*P\|I_AKAqIb0O4#\ cm=sl\)WWYwEg10DDv%k/\"c\{LrS\)oVd§4\>8bs:\;9u\$\ \*W_SGk3CXe7hZMm\$nXyhAuHDi-q+ug5+%ioou.\,IhC\]-_O§V\]\^\,2q:VBVyTTD6\'aNw9:oan\(s2SzV
You can use the escaped string directly in your shell, without additional quotes, like this:
python my_script.py 2m+\{N7HiwH3\[\>\!\"4y\?t9\*y#\;/\$Ar3wF9+k\$\[3hK/WA=aMzF°L0PaZTM\]t\*P\|I_AKAqIb0O4#\ cm=sl\)WWYwEg10DDv%k/\"c\{LrS\)oVd§4\>8bs:\;9u\$\ \*W_SGk3CXe7hZMm\$nXyhAuHDi-q+ug5+%ioou.\,IhC\]-_O§V\]\^\,2q:VBVyTTD6\'aNw9:oan\(s2SzV
In order to make life easier, shells like bash do a little bit of extra work to help users pass the correct arguments to the programs they instruct it to execute. This extra work usually results in predictable argument arrays getting passed to programs.
Oftentimes, though, this extra help results in unexpected arguments getting passed to programs; and sometimes results in the execution of undesired additional commands. In this case, though, it ended up causing Bash to emit an error.
In order to turn off this extra work, Bash allows users to indicate where arguments should begin and end by surrounding them by quotation marks. Bash supports both single quotes (') and double quotes (") to delimit arguments. As a last resort, if a string may contain single and double quotes (or double quotes are required but aren't aggressive enough), Bash allows you to indicate that a special- or whitespace-character should be part of the adjacent argument by preceding it with a backslash (\\).
If this method of escaping arguments is too cumbersome, it may be worth simplifying your program's interface by having it consume this data from a file instead of a command line argument. Another option is to create a program that loads the arguments from a more controlled location (like a file) and directly execs the target program with the desired argument array.

disable histexpand and variable substitution

I need to create many thousands of files and I have no control over the text strings that need to be used for the paths and names. Trouble is, these strings might contain ",',“,‘,! or $, all of which can cause problems.
I can replace all quotes with the normal apostrophe, but I want to keep any $ or ! characters and so far not been able to figure how to do this.
Set +H will turn off history expansion, but I cannot make it work within the same command. So:-
set +H; echo "Hi, this is $10 Tom!"
still generates the error due to the !. If I run them as 2 separate commands, histexpand stays off and it works, but running them both just separated by the ; does NOT change histexpand.
The problem is that the commands will be run in their own shell and I can't seem to run multiple lines (doShellScript in Apple's JXA) so need them on the same line just separated by the ;.
So how can I make the set +H stick for the immediately following command?
Also, is it possible to stop the shell from interpreting $ as preceding a variable and just deal with it as a regular character? I can't just quote the whole string with single quotes since it may contain ' within itself.
Suggestions?

How to pass a file name containing spaces as an argument to a command-line program?

Whenever I try to add a file with whitespace in its name to git, it shows an Error as
"fatal: pathspec 'Tic' did not match any files"
Since I was New to git and Linux based terminal I have no idea how to do it.
Screen-shot or my error:
You should be able to quote the filename (eg. "file name"), or use an escape sequence (eg. file\< space >name).
To expand on #ergonaut's correct answer, just for the sake of clarity, this is actually neither a git nor a Linux issue. This is just a general requirement for command lines across the board.
On any command line, each word (or in this case, string of words) is evaluated separately as either a command or a parameter to a command. So, for example, git's add command is expecting a single parameter to come immediately after it (a filename). In this case, the next word it sees is just "Tic". Since it's only looking for a single parameter, it stops evaluating anything else at that point and that's why it's complaining about not being able to find the "Tic" file. When the words are enclosed in quotes, the entire string is evaluated as a single parameter, therefore fixing the issue.
Always wrap filenames that contain spaces with quotes when using them on the command line. Or even better, avoid using spaces in filenames. :-)
Try:
git add Tic\ tac\ toe.c
\ is used to escape special characters, though this is more bash related rather than git specific.
Alternatively, you could put the name of the file in quotes.
git add "Tic tac toe.c"
Start writing the first word and then press "Tab" button to use autocomplete
and you will be happy ))

Opening a file with an & in the middle --- Mac Terminal

This is just maddening--I have a file with an & sign in the middle of it. When my python script went to open it, the & sign acted as an end of command character or something....
Can anyone tell me how to get around this? Or better yet, I would love to know where to look for a list of all of these special characters for the terminal.
Thanks in advance
--A mac noob
You can also surround the whole name with single quotes. Single quotes defend a filename from almost all kinds of interpretation - ampersands, angle brackets, whitespace, etc. They are often easier to use than backslashes, because you don't need to specifically apply them to every troublesome character, you just quote the whole filename.
Now, why was this a problem in a Python script? What were you doing that the shell's handling of filenames was relevant? That doesn't sound at all right.
The Bash command & means execute in background, it is interpreting & as a command and not an argument to your command, either remove it from the filename, which is good anyway, or escape it like \&
You can use the escape character, \. So all you have to do is put backslashes in this:
open file&with&an&ampersand.txt
To make it this:
open file\&with\&an\&ampersand.txt
in addition to #Tom answer i think you have to escape single quote in file names because files can have single quote in there name and you can do this by replacing single quote with '"'"' please check this answer: https://stackoverflow.com/a/1250279/427622

Resources