Why doesn't the pipe command work for me? - bash

Actually in my last question I was trying to use the pipe command. I am looking at an example in Process Substitution - Advanced Bash-Scripting Guide.
I tried these lines:
bzip2 -c < pipe > file.tar.bz2 &
tar cf pipe $directory_name
rm pipe
But they are failing with an error:
pipe: No such file or directory.
What's happening here? Is this an error in the ABS guide?

The example you're using appears to assume that the named pipe called "pipe" already exists in the current directory. The "pipe" in here:
bzip2 -c < pipe > file.tar.bz2 &
is not a command name, it is a file name that happens to be a named pipe. Do some reading on "mkfifo" and "named pipes" for more information.

Related

bash, how to dot source a downloaded file (using curl) into bash

I have .sh file that I would like to dotsource into my running environment. This does not work:
curl -s https://raw.githubusercontent.com/bla/bla/master/stuff.sh | bash
The above does not work, i.e. The script runs, but the environment variables and things inside stuff.sh are not dotsourced into the running environment. I also tried:
. curl -s https://raw.githubusercontent.com/bla/bla/master/stuff.sh | bash
curl -s https://raw.githubusercontent.com/bla/bla/master/stuff.sh | bash source
curl -s https://raw.githubusercontent.com/bla/bla/master/stuff.sh | source bash
All fail. Would appreciate knowing how this can be done?
I am not a bash expert, but if you are willing to accept some drawbacks, the easiest method to do that is without pipes. I believe that it should be possible when you separate download and sourcing:
prompt># curl -s https://raw.githubusercontent.com/bla/bla/master/stuff.sh > ./stuff.sh
prompt># . ./stuff.sh
From the bash manual (man bash), in the chapter about the builtin source command:
Read and execute commands from filename [...]
There is no mentioning about standard input as a possible source for the commands which should be sourced.
However, as hanshenrik stated in his answer, you always can use process substitution to create a temporary (and invisible on the file system) file which you can feed to source. The syntax is <(list), where <(list) is expanded to a unique file name chosen by bash, and list is a sequence of commands whose output is put into that file (the file does not appear on the file system, though).
Process substitution is documented in the bash manual (man bash) in a paragraph under that exact caption.
try
source <(curl -s https://raw.githubusercontent.com/bla/bla/master/stuff.sh)
i tried doing
curl -s https://raw.githubusercontent.com/bla/bla/master/stuff.sh | source /dev/stdin
but that didn't work for some reason, no idea why (anyone knows?)

Error in executing command tar -xjf

While executing command in shell script like as follows i am getting an error please help
tar -xjf $tarfile
error is :
tar: option requires an argument -- f
Then the variable $tarfile is obiviously empty. Argument f requires a filename or a hyphen to denote stdin allowing for piping of data to tar. The j argument expects to find the tarfile compressed in bzip2 format.
In your script you would have to do something similar:
tarfile=/path/to/file.tar.bz2
tar -xjf $tarfile
or an example of piping:
ssh user#remotehost cat /path/to/file.tar.bz2|tar -xjf -
This happens because the $tarfile variable is empty.

/proc directory script

I'm looking for a ruby script that accesses the /proc directory and saves the process ID and command line (cmdline) information in a file.
you may want to call ps instead of going to /proc.
cmd=`ps -eo pid,cmd`
o = File.open("output","w")
o.write(cmd)
o.close
you can also run below one liner bash script and redirect its output anywhere, as well as choose required argument option for head command.
ls -alR /proc/$(ls /proc/ |grep -i '[0-9]'|sort -n|head ) > /proc_open_files

BASH Unexpected EOF

My Mac keeps telling my unexpected end of file for this bash script, on the last line. I am not new to programming but very new to BASH, does anyone see anything wrong with this?
#!/bin/bash
#bootstrapper.sh
PIDD="$5"
while sleep 1; do kill -0 $PIDD || break; done
# Absolute path to this script. /home/user/bin/foo.sh
SCRIPT=$(readlink -f $0)
# Absolute path this script is in. /home/user/bin
SCRIPTPATH=`dirname $SCRIPT`
POSPAR1="$1" #-l
POSPAR2="$2" #location
POSPAR3="$3" #-d
POSPAR4="$4" #directory
cp -r -f $SCRIPTPATH/$4/* $2
rm -r -f $SCRIPTPATH/$4
Thank you in advance!
I coped your code from the question on a Mac (copy'n'paste) and ran the file with:
bash -n -v x.sh
In fact, I did that twice; the first time, I ensured there was a newline at the end of the file, and the second time I ensured that there wasn't a newline. And bash was quite happy both times.
This indicates to me that the problem is not in the visible characters; there are some invisible characters in the file causing grief. You will probably need to scrutinize the file with a tool such as od -c to find the character that is causing the trouble.
Also, FWIW, the readlink command on my Mac gives:
$ readlink -f $0
readlink: illegal option -- f
usage: readlink [-n] [file ...]
$
The Linux version of readlink takes -f. It isn't a POSIX command, so there is no de jure standard to refer to.
Analyzing the file with od -c revealed the line ending were \r\n, I did modify the file one Windows, silly me. Anyway, I am having another issues with the BASH script. This line:
while sleep 1; do kill -0 $PIDD || break; done
Is supposed to wait until the PID (stored in variable $PIDD) closes. It waits until it doesn't exist (the PID), but when it finally doesn't exist, it outputs: kill: 4: No such process. The rest of the script works as intended, but then the script doesn't terminate. Can I make the script terminate properly and not have that No such process be outputted?
Sorry for all the newbie questions, I'm awful at BASH and Linux.
Thanks again for all your help.

xargs with command that open editor leaves shell in weird state

I tried to make an alias for committing several different git projects. I tried something like
cat projectPaths | \
xargs -I project git --git-dir=project/.git --work-tree=project commit -a
where projectPaths is a file containing the paths to all the projects I want to commit. This seems to work for the most part, firing up vi in sequence for each project so that I can write a commit msg for it. I do, however, get a msg:
"Vim: Warning: Input is not from a terminal"
and afterward my terminal is weird: it doesn't show the text I type and doesn't seem to output any newlines. When I enter "reset" things pretty much back to normal, but clearly I'm doing something wrong.
Is there some way to get the same behavior without messing up my shell?
Thanks!
Using the simpler example of
ls *.h | xargs vim
here are a few ways to fix the problem:
xargs -a <( ls *.h ) vim
or
vim $( ls *.h | xargs )
or
ls *.h | xargs -o vim
The first example uses the xargs -a (--arg-file) flag which tells xargs to take its input from a file rather than standard input. The file we give it in this case is a bash process substitution rather than a regular file.
Process substitution takes the output of the command contained in <( ) places it in a filedescriptor and then substitutes the filedescriptor, in this case the substituted command would be something like xargs -a /dev/fd/63 vim.
The second command uses command substitution, the commands are executed in a subshell, and their stdout data is substituted.
The third command uses the xargs --open-tty (-o) flag, which the man page describes thusly:
Reopen stdin as /dev/tty in the child process before executing the
command. This is useful if you want xargs to run an interactive
application.
If you do use it the old way and want to get your terminal to behave again you can use the reset command.
The problem is that since you're running xargs (and hence git and hence vim) in a pipeline, its stdin is taken from the output of cat projectPaths rather than the terminal; this is confusing vim. Fortunately, the solution is simple: add the -o flag to xargs, and it'll start git (and hence vim) with input from /dev/tty, instead of its own stdin.
The man page for GNU xargs shows a similar command for emacs:
xargs sh -c 'emacs "$#" < /dev/tty' emacs
(in this command, the second "emacs" is the "dummy string" that wisbucky refers to in a comment to this answer)
and says this:
Launches the minimum number of copies of Emacs needed, one after the
other, to edit the files listed on xargs' standard input. This example
achieves the same effect as BSD's -o option, but in a more flexible and
portable way.
Another thing to try is using -a instead of cat:
xargs -a projectPaths -I project git --git-dir=project/.git --work-tree=project commit -a
or some combination of the two.
If you have GNU Parallel http://www.gnu.org/software/parallel/ installed you should be able to do this:
cat projectPaths |
parallel -uj1 git --git-dir={}/.git --work-tree={} commit -a
In general this works too:
cat filelist | parallel -Xuj1 $EDITOR
in case you want to edit more than one file at a time (and you have set $EDITOR to your favorite editor).
-o for xargs (as mentioned elsewhere) only works for some versions of xargs (notably it does not work for GNU xargs).
Watch the intro video to learn more about GNU Parallel http://www.youtube.com/watch?v=OpaiGYxkSuQ
Interesting! I see the exact same behaviour on Mac as well, doing something as simple as:
ls *.h | xargs vim
Apparently, it is a problem with vim:
http://talideon.com/weblog/2007/03/xargs-vim.cfm

Resources