Tag Info

New answers tagged

3

When you have a command such as this sed -e ... "datafile" >"datafile" You will end up with a zero length result. The reason is that the shell sets up stdin and stdout before it executes the command. So stdout is sent to the file datafile, creating or truncating it in the process, and only then is the sed -e ... "datafile" run. A common solution is ...


0

Have discovered an utility that promises to provide pipes without the need for a separate new daemonized bash script. May come in handy: https://github.com/flonatel/pipexec pipexec -- [NETCAT netcat localhost 1099] [LOOP bash loop.sh] '{NETCAT:1>LOOP:0}'


4

POSIX command/process substitution _log()( x=0 while [ -e "${TMPDIR:=/tmp}/$$.$((x+=1))" ] do continue; done && mkfifo -- "$TMPDIR/$$.$x" && printf %s\\n "$TMPDIR/$$.$x" || exit exec >&- >/dev/null { rm -- "$TMPDIR/$$.$x" logger --priority user."$1" --tag "${0##*/}" } ...


6

There's no POSIX equivalent. You can only perform a redirection with exec, not a fork. A pipe requires a fork, and the shell waits for the child to finish. One solution is to put all your code in a function. all_my_code () { … } { all_my_code | logger --priority user.notice --tag "$(basename "$0")"; } 2>&1 | logger --priority user.error --tag ...


1

A pipe, just like any file, is a stream of text (more precisely, a stream of bytes). The basic building blocks of Unix tend to be simple. Interactions between processes are mostly based on unstructured data. The operating system doesn't provide a communication channel with multiple streams labeled by a file name. If programs need this, they need to arrange ...


1

That device looks much like net redirection in bash, for example /dev/tcp/server/22. On Ubuntu 15.04, I could ssh over such a device by putting the following lines in ~/.ssh/config, then running ssh xyz. Host xyz ProxyCommand bash -c 'exec 3<>/dev/tcp/server/22; cat <&3 & cat >&3' Could you try this with replacing ...


1

Are you talking about program1 file1.txt | program2 | program3 > folder/file1.txt program1 file2.txt | program2 | program3 > folder/file2.txt program1 file42.txt | program2 | program3 > folder/file42.txt program1 green.txt | program2 | program3 > folder/green.txt program1 indigo.txt | program2 | program3 > folder/indigo.txt program1 ...


3

In most unices you can reference a file descriptor by its device link. alpha(){ echo a b c | tr \ \\n; } alpha | { alpha | tr \[:lower:] \[:upper:] | paste - /dev/fd/9 } 9<&0 A a B b C c named pipes Ok, so I did have a pretty well working version of this already. The version open in my editor (as yet unfinished) is not ...


1

Pipe the password into the su, which in turn is piped to ssh. Example below. Note how foopass is the correct password for user foo, so it runs the id command happily. Note how badpass is the wrong password for user foo, so it generates Authentication failure. $ echo "echo foopass | su foo -c id" | ssh -t -o RequestTTY=yes steve@localhost Pseudo-terminal ...


0

$ tar -tzf x.tgz |grep -v '/$' | xargs -n1 -d '\n' echo rm Remove the echo if it looks good. Explanation: tar -tzf x.tgz -- list the contents grep -v '/$' -- skip directories xargs -n1 -d '\n' echo rm -- for each one (-n1) line (-d '\n') of input, run echo rm


0

May be something like this will help you rm -rf `find . -name '*.tgz' -exec tar -tzf '{}' \;` not sure how it will work with so many files.


2

You would need to be at the directory from which the tar file was created, for instance $HOME. Then if you had a tgz of your Documents directory located safely in /backup/Documents.tgz you would do this: $ for file in $(tar -tzf /backup/Documents.tgz); do \ [[ -f $file ]] && rm $file || echo "$file does not exist"; done If you want to also ...


1

you can try tac /DIRECTORY/TO/FILE.csv | sed -e 's/o,632/o,101/g' -e 's/o,938/o,103/g' -e 's/o,510/o,112/g' -e 's/ombo,713/ombo,102/g' | while read f1 f2 f3 f4 f5 f6 f7 f8 f9 f10 f11 f12 f13 f14 f15 do if [ "$f7" = "EnHr" ] && [ "$f10" -gt 0 ] && [ "$f4" = "$m_class" ] && [ "$f5" = "$m_id" ] then ...


1

<<< in bash is a here string. You passed your script string itself tac /DIRECTORY/TO/FILE.csv ... to while's stdin. You might have wanted to use process substitution: while read f1 f2 f3 f4 f5 f6 f7 f8 f9 f10 f11 f12 f13 f14 f15 do ... done < <(tac /DIRECTORY/TO/FILE.csv ...)


1

you like | do you ? the best I come with current_ip=$(ifconfig eth0 | awk '$1 == "inet" { split($2,A,":") ; print A[2] ; } ') netstat -plant | grep $current_ip | awk '{split($5,A,":") ; howmany[A[1]]++ ; } END { for (h in howmany) printf "%d %s \n",howmany[h],h ;} '| sort -nr | while read hm ho do name=$(host $ho|awk '{print $NF}') echo $hm $ho ...


3

If you get rid of the killing and shutdown stuff (which is unsafe and you may, in an extreme, but not unfathomable case when child.py dies before the (head -n 1 shutdown; kill -9 $parent) & subshell does end up kill -9ing some innocent process), then child.py won't be terminating because your parent.py isn't behaving like a good UNIX citizen. The cat ...


2

With a sed the input will always be read in on a line-buffer, and the output can be explicitly flushed per line with the w command. For example: ( cd /tmp; c= mkfifo i o dd bs=1 <o& sed -n w\ o <i& while sleep 1 do [ -z "$c" ] && rm [io] [ "$c" = 5 ] && ...


0

In bash, you could try: forward() { while read line; do echo "$line"; done; } forward </tmp/out & forward </tmp/err >&2 & forward >/tmp/in wait and then run the script with stdbuf -i0 -oL. The forward function is basically your the pipe method from your python code with src and dest defaulting to stdin and stdout and without the ...


-1

Since you're using bash anyway, you should be using $SECONDS: #!/bin/bash while [ "$SECONDS" -lt 5 ] || { SECONDS=$((i=0)) echo Something different };do sleep "$((r=(1+RANDOM)%3))" echo "$((i+=r))" done From man bash: $SECONDS This variable expands to the number of seconds since the shell was started. Assignment to this ...


3

n=$some_num { head -n"$(($(wc -l <in)-n))" >/dev/null grep 'match your string' } <in Unfortunately this requires reading the file entirely through w/ wc to get a line-count because it's not clear otherwise how many lines are in the file or how large $n is. That aside, this should be a very performant solution provided <in is a regular, ...


2

You can do that with awk and a little bit of help: $ N=8 $ awk -v start_line="$(( $(wc -l < alphabet) - N + 1 ))" 'NR>=start_line && /e/' alphabet sierra whiskey yankee $ finds all lines containing e in the last 8 lines of the phonetic alphabet.  This has the drawback that it reads the entire input file twice.


4

If your shell supports it (zsh, bash, some implementations of ksh), you could utilise process substitution grep <pattern> <(tail -n5 yourfile.txt) Where -n5 means get the five last lines. Similarly, grep <pattern> <(head -n5 yourfile.txt) would search through the 5 first lines of yourfile.txt. Explanation Simply speaking, the ...


2

Why do you want to avoid pipe? If you really want to avoid pipe, then you will have to run two commands: tail -N filename > filename.tmp grep "string" filename.tmp (when N is the last number of lines)


1

Here is the code I am running now, based on airfishey's answer with some corrections. #!/bin/bash t_lastdue=$(date --date='5seconds ago' +%s) while true do t_now=$(date +%s) t_elapsed=$((t_now - t_lastdue)) if [ $t_elapsed -ge 5 ] then echo 'Something different' t_lastdue=$((t_lastdue + 5)) i=0 else # ...


3

First of all, in case it isn't obvious, the script in the question fails because heartbeat runs in a child process, and therefore cannot change shell variables in the parent shell's memory. Here's an approach that's closer to the spirit of the OP's attempt: #!/bin/bash trap 'do_different=true' USR1 heartbeat() { while sleep 5 do ...


1

I would use the date utility to get the current time in seconds. #!/bin/bash lastTime=-5 while true do currentTime=$(date +%s) elapsedTime=$((currentTime - lastTime)) if [[ $elapsedTime -ge 5 ]] then echo 'Something different' lastTime=$currentTime i=0 else # process of random duration; not important ...


0

If you want to grab the first interface that has an IPv4 address, you can run ifconfig just once to display all the interfaces and extract the first entry with an IPv4 address. You can also optimize the extraction by combining what you're doing with grep and awk. ifconfig -a | awk '/^[^ ]/ {iface=$1} iface ~ /^eth/ && sub(/inet ...


2

Another more modular approach: not bash-specific get_ifconfig () { for iface do ifconfig "$iface" 2>/dev/null && return done } get_ifconfig eth1 eth2 eth3 | sed -n 's/.*inet addr:\([0-9.]\+\).*/\1/p'


0

How about this approach $ echo eth1 eth0 | xargs -n 1 ifconfig 2>/dev/null | awk '/inet/{gsub("addr:","",$2);print $2;exit}' 192.168.124.132 $


0

Try this: $ ( ifconfig eth2 2>/dev/null || ifconfig eth0 2>/dev/null ) | grep ... It has the same logic, but it does the || inside the parens so it only passes the output of the successful command to grep.


9

Use script(1) to log everything sent to the terminal: $ script Script started, file is typescript $ # do your work ... $ # then exit with ^D $ exit Script done, file is typescript You can later look at the output with less: $ less -r typescript Beware that the logs will contain all control characters sent to the terminal, such as ANSI colours or ...


0

I've since tried tackling the problem from a different angle, using the 'expect ' command. However the following fails to work: #!/usr/bin/expect spawn sudo mount.cifs "//192.168.1.2/My Pictures" /home/pi/Desktop/Pictures -o user=Rob_ expect "Password: " { set send_slow {1 .1} send -s "a_password" } It responds to the password prompt by typing it ...


-1

There are multiple reasons: Your debug printf didn't work, because mount prints its prompt to the terminal, not stdout. read prompt failed and the loop was never entered. You are trying to echo the password to /dev/stdin. This will not work, you can only read from it. the mount's stdin is still connected to the terminal. There is no way to emulate user ...


1

Use this with bash: TEST='{"foo": "bar"}' PB_SIG=$(jq '.foo' <<< "$TEST") echo "$PB_SIG" Output: "bar"


0

Try this on the second line: PB_SIG=`echo $TEST | jq '.foo'` The two problems I see is that you need to echo the $TEST variable's value through the pipe and that you need to capture the output of the piped command.


4

Okay, let's break this down. A subshell executes its contents in a chain (i.e., it groups them). This actually makes intuitive sense as a subshell is created simply by surrounding the chain of commands with (). But, aside from the contents of the subshell being grouped together in execution, you can still use a subshell as if it were a single command. That ...


1

subshell (command) will execute command in subshell, this is usefull, if you have more then one command. (ls) | wc will pipe ls to wc, obviously you can write ls | wc (ls ; date) | wc will pipe the result of both ls and date to wc. using ls ; date | wc will result in only date being piped to wc. substitution $(command) will execute command and ...


2

You don't have to get the whole lump if you don't want to - you can chunk out stdin and work it as a stream if you like. I did some googling, though, and I don't think I can offer you any advice on how to change the sex of your script, or whatever it is you meant by polymorphic. In any case, I typically find that putting the whole of input aside in some ...


3

You can read from stdout by redirecting input from file descriptor 1. Stdout is file descriptor 1 by definition. The fact that file descriptor 1 is used for output is a matter of convention, not a technical obligation. However it's a bizarre thing to do which is bound to confuse the people who use your script. read line <&1 If you want to read a ...


2

If you want to read all of stdin into a shell script, usually you just capture it into a temp file: TMPFILE=$(mktemp /tmp/$0.$$.XXXXXX) cat > "$TMPFILE" # Script works with $TMPFILE and its contents, # ultimately writing everything to stdout. rm -f "$TMPFILE" Even system utilities do things very much like this. sort has to have all of stdin before it ...


3

A pipe sends its output to the program that has it open for reading. In a shell pipeline, that's the program on the right-hand side of the pipe symbol, i.e. evince in your example. You're sending the file name tmp.pdf to evince on its standard input. However evince doesn't care about its standard input. Like every program that acts on a file, it expects the ...


1

I can't find a way with the pipe but you can try this: obexftp -b 10:68:3F:57:7D:B6 - p $(cat inputFile.tar) Return the sdout of the command in the $( )


3

That's the effect of MULTIOS. echo foo >&2 | grep foo will write foo to stderr and also pipe foo to grep. Because stderr defaults to terminal, you will see two foo lines, one from echo, one from the grep result. { echo foo >&2 | grep foo } >/dev/null Here, you saw one line because stdout was redirected to /dev/null, you only saw the ...


6

Your understanding is correct. The sequence command1 | command2 is sending the output (STDOUT) of command1 to the input (STDIN) of command2. The reason your evince command didn't work is that evince doesn't accept a filename on STDIN.



Top 50 recent answers are included