Why is this redirection not working in my zsh script? - zsh

I have a zsh script which includes the line
rm *original > /dev/null 2>&1
but when those files aren't there, I get
no matches found: *original
to the terminal/screen.
Now, I've been retired for ten years, but memory tells me that has worked before in other shells. How is zsh different? I did a web search for "zsh redirection," but got pages on bash instead.

Related

Redirect not working correctly, 2> /dev/null becomes 2 > /dev/null and stderr doesn't get redirected

I am hoping someone can help me figure out what setting I might need to overwrite. I am working on a Unix terminal server, running a Linux Xterm linux shell. Everytime I use a command like grep "blah" 2> /dev/null at the shell prompt, the command is run as grep "blah" 2 > /dev/null and needless to say the redirection fails.
xterm version is X.Org 6.8.99.903(238)
I can not update or install anything, this is a locked down production server.
Thanks for any help and illumination on the topic, it is making my grep useless at high directory levels with recursion.
That's Bourne shell syntax, and it doesn't work in c-shell.
The best you can do is
( command >stdout_file ) >&stderr_file
Where you get stdout to one file, and stderr to another. Redirecting just stderr is not possible.
In a comment, you say "A minor note, this is csh". That's not a minor note, that's the cause of the problem. xterm is just a terminal emulator, not a shell; all it does is set up a window that provides textual input and output. csh (or bash, or ...) is the shell, the program that interprets the commands you type.
csh has different syntax for redirection, and doesn't let you redirect just stderr. command > file redirects stdout; command >& file redirects both stdout and stderr.
You say the system doesn't have bash, but it does have ksh. I suggest just using ksh; it will be a lot more familiar to you. Both bash and ksh are derived from the old Bourne shell.
All (?) Unix-like systems will have a Bourne-like shell installed as /bin/sh. Even if you're using csh (or tcsh?) as your interactive shell, you can still invoke sh, even in a one-liner. For example:
sh -c 'command 2>/dev/null'
will invoke sh, which in turn will invoke command and redirect just its stderr to /dev/null.
The purpose of an interactive shell is (mostly) to let you use other commands that are available on the system. sh, or any shell, can be used as just another command.

Removing files - Silent failure issue

In a Unix environment, I have a bash script that removes some files:
rm -f foo bar* baz*
My problem: not always the wildcard returns any result. And as a result of that, I fail to remove even 'foo' which always exists. The output written is "rm: No match".
A simple workaround would be to split the command:
rm -f foo
rm -f bar*
rm -f baz*
But it's a bad solution.
No it should work. Which shell is used ? Is rm an internal version or an external ? (Try /bin/rm instead to ensure the external version). You may have some shell option set that prevent you to execute the command in that case (this may depend on your shell).

xmlstarlet not working correct in mac

I created a batch file for windows that executes some xmlstarlet commands. I want to write it as .sh file so that i can run it on mac. The problem is.. Some commands are working fine in windows but not in mac. It didn't show any error too. Eg.
**xml ed -L -d //intent-filter//category[#android:name='android.intent.category.LAUNCHER'] my_folder\AndroidManifest.xml**
In windows, above command deletes the mentioned xml tag. BUt it does nothing in mac.
But the command
**xml sel -t -m //manifest -v //manifest/#package mim_apk_proj\AndroidManifest.xml**
is working fine in both mac and windows.
I have installed xml tool. Checked /usr/local/bin. It has libxslt.dylib and libxml2.dylib. I dont know where the problem lies?
Can someone help?
The quoting rules for bash (that's the shell on your mac, right?) are different from cmd.exe (the Windows shell), in particular, cmd.exe treats ' as a normal character while to bash it is a quoting character so it isn't passed to the program. In bash you therefore need to quote the 's as well:
xml ed -L -d //intent-filter//category[#android:name='android.intent.category.LAUNCHER'] my_folder\AndroidManifest.xml
# becomes
xml ed -L -d "//intent-filter//category[#android:name='android.intent.category.LAUNCHER'] my_folder\AndroidManifest.xml"
# or, since XPath treats both kinds of quotes identically you can also use
xml ed -L -d '//intent-filter//category[#android:name="android.intent.category.LAUNCHER"] my_folder\AndroidManifest.xml'
The second fix is safer because it also prevents bash from doing any variable expansion if you use $, but the first fix has the advantage of working in Windows as well.

strange behavior of fc -l command

I have two unix machines, both running AIX 5.3
My $HOME is mounted on machine1.
Using NFS, login machine2 will go to the same $HOME
I login machine2 first, then machine1.
Both using telnet.
The 2 sessions will share the same .sh_history file.
I found out that the fc -l behavior very strange.
In machine2, I issue the commands in telnet:
fc -l
ksh fc -l
Both give the same output.
In machine1,
fc -l
ksh fc -l
give DIFFERENT results
The result for ksh fc -l
is the same as /usr/bin/fc -l
Also, when I run a script like this:
#!/usr/bin/ksh
fc -l
The result is same as /usr/bin/fc -l
Could anyone tell me what happened?
Alvin SIU
Ah, wisdom of the ancients... (Since this post is over a year old.)
Anyway, I just encountered this problem in Solaris 10. Issue seems to be this: When you define a function in /etc/profile, or in any file called by /etc/profile, your HISTFILE variable gets ignored by the Korn shell, and the shell instead uses ".sh_history" when accessing its history. Not sure why this is.
Result is that you see other root shell's commands. You can test it with :
lsof -p $$
or
cat /proc/$$/fd/63
It's possible that the login shell is not ksh or that $HISTFILE is being reset. One thing you can do is echo $HISTFILE in the various situations and see if it's different. Another thing to check is to see what shell you're in using ps.
Bash (default $HOME/.bash_history), for example, will have a different $HISTFILE than ksh (default $HOME/.sh_history).
Another possible reason for the difference is that the builtin fc may be able to see in-memory history that hasn't been written to disk yet (which the external /usr/bin/fc wouldn't be able to see). If this is true, it may be version dependent. Bash, for example, doesn't write history to the file until the shell exits. Ksh (at least the version I'm using) writes it immediately.

Whats the difference between running a shell script as ./script.sh and sh script.sh

I have a script that looks like this
#!/bin/bash
function something() {
echo "hello world!!"
}
something | tee logfile
I have set the execute permission on this file and when I try running the file like this
$./script.sh
it runs perfectly fine, but when I run it on the command line like this
$sh script.sh
It throws up an error. Why does this happen and what are the ways in which I can fix this.
Running it as ./script.sh will make the kernel read the first line (the shebang), and then invoke bash to interpret the script. Running it as sh script.sh uses whatever shell your system defaults sh to (on Ubuntu this is Dash, which is sh-compatible, but doesn't support some of the extra features of Bash).
You can fix it by invoking it as bash script.sh, or if it's your machine you can change /bin/sh to be bash and not whatever it is currently (usually just by symlinking it - rm /bin/sh && ln -s /bin/bash /bin/sh). Or you can just use ./script.sh instead if that's already working ;)
If your shell is indeed dash and you want to modify the script to be compatible, https://wiki.ubuntu.com/DashAsBinSh has a helpful guide to the differences. In your sample it looks like you'd just have to remove the function keyword.
if your script is at your present working directory and you issue ./script.sh, the kernel will read the shebang (first line) and execute the shell interpreter that is defined. you can also call your script.sh by specifying the path of the interpreter eg
/bin/bash myscript.sh
/bin/sh myscript.sh
/bin/ksh myscript.sh etc
By the way, you can also put your shebang like this (if you don't want to specify full path)
#!/usr/bin/env sh
sh script.sh forces the script to be executed within the sh - shell.
while simply starting it from command line uses the shell-environemnt you're in.
Please post the error message for further answers.
Random though on what the error may be:
path specified in first line /bin/bash is wrong -- maybe bash is not installed?

Resources