Using pipes with find command in linux
You could just use the verbose flag on rm and it will tell you what it's deleting
find ~/ -name "~*" | sort -n | head -5 | xargs rm -v
Use man rm
to see the docs
-v, --verbose
explain what is being done
Pipe Find command stderr to a command
Pipe stderr and stdout simultaneously - idea taken from this post:
(find /boot | sed s'/^/STDOUT:/' ) 3>&1 1>&2 2>&3 | sed 's/^/STDERR:/'
Sample output:
STDOUT:/boot/grub/usb_keyboard.mod
STDERR:find: `/boot/lost+found': Brak dostępu
Bash redirections like 3>&1 1>&2 2>&3
swaps stderr and stdout.
I would modify your sample script to look like this:
#!/bin/bash
ErrorFile="error.log"
(find ./subdirectory -type f 3>&1 1>&2 2>&3 | sed "s#^#${PWD}: #" >> $ErrorFile) 3>&1 1>&2 2>&3 | while read line; do
field1=$(echo "$line" | cut -d / -f2)
...
done
Notice that I swapped stdout & stderr twice.
Small additional comment - look at -printf
option in find manual page. It might be useful to you.
Linux cli pipe output of command into another command
The bash builtin command mapfile
may be what you're looking for. It reads the lines of output into an array.
mapfile -t files < <(find . -name *.txt)
The redirection from a process substitution is required to avoid subshells.
Then
- the first file is in
"${files[0]}"
- the last file is in
"${files[-1]}"
- all the files are
"${files[@]}"
Inspect the array with declare -p files
Unix pipe into ls
To do that you need xargs
:
which studio | xargs ls -l
From man xargs
:
xargs - build and execute command lines from standard input
To fully understand how pipes work, you can read What is a simple explanation for how pipes work in BASH?:
A Unix pipe connects the STDOUT (standard output) file descriptor of
the first process to the STDIN (standard input) of the second. What
happens then is that when the first process writes to its STDOUT, that
output can be immediately read (from STDIN) by the second process.
bash - how to pipe result from the which command to cd
You use pipe in cases where the command expects parameters from the standard input. ( More on this ).
With cd
command that is not the case. The directory is the command argument. In such case, you can use command substitution. Use backticks or $(...)
to evaluate the command, store it into variable..
path=`which oracle`
echo $path # just for debug
cd $path
although it can be done in a much simpler way:
cd `which oracle`
or if your path has special characters
cd "`which oracle`"
or
cd $(which oracle)
which is equivalent to backtick notation, but is recommended (backticks can be confused with apostrophes)
.. but it looks like you want:
cd $(dirname $(which oracle))
(which shows you that you can use nesting easily)
$(...)
(as well as backticks) work also in double-quoted strings, which helps when the result may eventually contain spaces..
cd "$(dirname "$(which oracle)")"
(Note that both outputs require a set of double quotes.)
How can I pipe output, from a command in an if statement, to a function?
The Print
function doesn't read standard input so there's no point piping data to it. One possible way to do what you want with the current implementation of Print
is:
if ! occ_output=$(sudo -u "$web_user" "$nextcloud_dir/occ" files:scan --all 2>&1); then
Print "Error: Failed to scan files. Are you in maintenance mode?"
fi
Print "'occ' output: $occ_output"
Since there is only one line in the body of the if
statement you could use ||
instead:
occ_output=$(sudo -u "$web_user" "$nextcloud_dir/occ" files:scan --all 2>&1) \
|| Print "Error: Failed to scan files. Are you in maintenance mode?"
Print "'occ' output: $occ_output"
The 2>&1
causes both standard output and error output of occ
to be captured to occ_output
.
Note that the body of the Print
function could be simplified to:
[[ $quiet_mode == No ]] && printf '%s\n' "$1"
(( logging )) && printf '%s\n' "$1" >> "$log_file"
See the accepted, and excellent, answer to Why is printf better than echo? for an explanation of why I replaced echo "$1"
with printf '%s\n' "$1"
.
An error occurred while processing STDERR using the pipe
The issue here is "multiple redirect".
The reason this can not be reproduced on Ubuntu, is because Ubuntu (like many Debian based Linux distros) uses Ash or Bash shell by default, while recent MacOS version switched to using ZSH.
ZSH on Ubuntu will give similar result to what you are getting.
Apparently, using both redirect >
and pipe |
causes ZSH to split you stderr
similar to tee
command.
This post shows a solution to the problem:
https://unix.stackexchange.com/questions/265061/how-can-i-pipe-only-stderr-in-zsh
Specifically, you need to close stdout
before redirecting it to /dev/null
to prevent the split:
cat test foo 2>&1 >&- > /dev/null | cut -d ':' -f 3
This works with ZSH on Ubuntu, and should work on Mac OS.
If it does not, check the linked post for enabling mult_ios
option in your shell.
Related Topics
How to Change Permissions to Certain File Pattern/Extension
How to Get the Exit Code of Spawned Process in Expect Shell Script
"Couldn't Find a File Descriptor Referring to the Console" on Ubuntu Bash on Windows
List File Using Ls Command in Linux with Full Path
Finding Executable Files Using Ls and Grep
A Light Solution to Convert Text to PDF in Linux
How to Recover After Deleting the Symbolic Link Libc.So.6
Permission Denied When Trying to Append a File to a Root Owned File with Sudo
Matlab Execute Script from Linux Command Line
How to Read Ring Buffer Within Linux Kernel Space
Expand a Possible Relative Path in Bash
Redirecting Output of Bash for Loop
How to Define a Bash Alias as a Sequence of Multiple Commands
Delete a Column from a Delimited File in Linux
How to Split Mailbox into Single File Per Message
Command Not Found in Bash's If-Else Condition When Using [! -D "$Dir"]