That's an odd request!
I'd use find
+ awk
to grab a file in the deepest directory:
bash-3.2$ deepest=$(find / -type f | awk -F'/' 'NF > depth {
> depth = NF;
> deepest = $0;
> }
>
> END {
> print deepest;
> }')
Using ${deepest}
in your mv
command is left as an exercise but the following five lines may help you further:
bash-3.2$ echo "${deepest}"
/Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/gems/1.8/gems/activesupport-2.3.5/lib/active_support/vendor/tzinfo-0.3.12/tzinfo/definitions/America/Argentina/Buenos_Aires.rb
bash-3.2$ echo "${deepest%.*}"
/Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/gems/1.8/gems/activesupport-2.3.5/lib/active_support/vendor/tzinfo-0.3.12/tzinfo/definitions/America/Argentina/Buenos_Aires
bash-3.2$ echo "${deepest%/*}"
/Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/gems/1.8/gems/activesupport-2.3.5/lib/active_support/vendor/tzinfo-0.3.12/tzinfo/definitions/America/Argentina
bash-3.2$ echo "${deepest##*/}"
Buenos_Aires.rb
bash-3.2$ echo "${deepest##*.}"
rb
Following update to question:
find -type d
[...] "This would only find the directory. [...] How could this be solved in the most simple way?".
By supplying -type f
to find
to find all files (f
), not all directories (d
).
It is working.
The different parts of a pipeline are executed concurrently. The only thing that synchronises/serialises the processes in the pipeline is IO, i.e. one process writing to the next process in the pipeline and the next process reading what the first one writes. Apart from that, they are executing independently of each other.
Since there is no reading or writing happening between the processes in your pipeline, the time take to execute the pipeline is that of the longest sleep
call.
You might as well have written
time ( foo.sh & bar.sh &; wait )
Terdon posted a couple of slightly modified example scripts in the chat:
#!/bin/sh
# This is "foo.sh"
echo 1; sleep 1
echo 2; sleep 1
echo 3; sleep 1
echo 4
and
#!/bin/sh
# This is "bar.sh"
sleep 2
while read line; do
echo "LL $line"
done
sleep 1
The query was "why does time ( sh foo.sh | sh bar.sh )
return 4 seconds rather than 3+3 = 6 seconds?"
To see what's happening, including the approximate time each command is executed, one may do this (the output contains my annotations):
$ time ( env PS4='$SECONDS foo: ' sh -x foo.sh | PS4='$SECONDS bar: ' sh -x bar.sh )
0 bar: sleep 2
0 foo: echo 1 ; The output is buffered
0 foo: sleep 1
1 foo: echo 2 ; The output is buffered
1 foo: sleep 1
2 bar: read line ; "bar" wakes up and reads the two first echoes
2 bar: echo LL 1
LL 1
2 bar: read line
2 bar: echo LL 2
LL 2
2 bar: read line ; "bar" waits for more
2 foo: echo 3 ; "foo" wakes up from its second sleep
2 bar: echo LL 3
LL 3
2 bar: read line
2 foo: sleep 1
3 foo: echo 4 ; "foo" does the last echo and exits
3 bar: echo LL 4
LL 4
3 bar: read line ; "bar" fails to read more
3 bar: sleep 1 ; ... and goes to sleep for one second
real 0m4.14s
user 0m0.00s
sys 0m0.10s
So, to conclude, the pipeline takes 4 seconds, not 6, due to the buffering of the output of the first two calls to echo
in foo.sh
.
Best Answer
Ctrl+C causes a SIGINT to be sent to all processes in the pipeline (as they're all run in the same process group that correspond to that foreground job of your interactive shell).
So in:
Both the process running
loopHelloWorld
and the one running the subshell that runs thewhile
loop will get theSIGINT
.If
loopHelloWorld
writes theCtrl+C to nicely shutdown
message on its stdout, it will also be written to the pipe. If that's after the subshell at the other end has already died, thenloopHelloWorld
will also receive a SIGPIPE, which you'd need to handle.Here, you should write that message to stderr as it's not your command's normal output (doesn't apply to the
ping
example though). Then it wouldn't go through the pipe.Or you could have the subshell running the while loop ignore the SIGINT so it keeps reading the
loopHelloWorld
output after the SIGINT:that would however cause the exit status of the pipeline to be 0 when you press Ctrl+C.
Another option for that specific example would be to use
zsh
orksh93
instead ofbash
. In those shells, thewhile
loop would run in the main shell process, so would not be affected by SIGINT.That wouldn't help for
loopHelloWorld | cat
though wherecat
andloopHelloWorld
run in the foreground process group.