find: output to a file with a comment - bash

I have a line that will generate the md5sum into a file from files included:
find / -type f \( -name "*.pl" -o -name "*.py" \) | md5sum *.pl *.py >> sum.txt
The sum.txt will output:
d41d8cd98f00b204e9800998ecf8427e file.pl
60b725f10c9c85c70d97880dfe8191b3 file.py
I would need to include the server name after the file name, preferably reading $HOSTNAME as the script will run on different servers, as:
d41d8cd98f00b204e9800998ecf8427e file.pl host.one.com
60b725f10c9c85c70d97880dfe8191b3 file.py host.one.com

The command will search through all *.pland *.py files. find will exec with md5sum command and a hostname will be added to each line. Both commands will generate same output:
find / -type f \( -name "*.pl" -o -name "*.py" \) -exec md5sum {} + | awk -v ORS=" $HOSTNAME\n" 1. >> sum.txt
find / -type f -name "*.p[ly]" -exec md5sum {} + |awk -v "h=$HOSTNAME" '{print $0,h}' >> sum.txt

An alternative would be to use find's -regex and to use sed for appending the hostname:
find / -type f -regex '.*\.\(py\|pl\)' -exec md5sum {} + | sed 's/$/ '"$HOSTNAME'/'

Related

KSH88 variable inside script

I'm having trouble with KSH88
script="find . ! \( "$result" \) -mtime "$older" -xdev -type f -size +"$minsize"M -exec ls -lh {} \; | head -100 | awk '{print \$8}' | sort -rn"
files_to_delete=`$script`
When I Echo my files_to_delete variable I get :
find . ! \( -name '*.jar' -o -name '*.zip' -o -name '*.rar' -o -name '*.log' -o -name '*.xml' \) -mtime 10 -xdev -type f -size +100M -exec ls -lh {} \; | head -100 | awk '{print $8}' | sort -rn
which is what I want, when I execute it on the command line it works, but when I execute it in my KSH I get
find: bad option \(
find: [-H | -L] path-list predicate-list
Put "eval " in front of the "$script", so it becomes
files_to_delete=`eval $script`
This forces the shell to evaluate the command string.
If your shell supports it, it woudl be better to use files_to_delete=$(eval $script). The ` version is easier to miss when scanning the script quickly, and much harder to nest (commands within commands).

Append line break to every cat in pipe

I have the following pipeline:
find /my/place -name 'test_*_blub' | xargs cat
While this works fine, I also want to have all file content terminated by a line break (\n).
Could not yet figure out how to append the newline.
To print a linebreak \n after each file content - use one of the following approaches:
1) running shell commands
find /my/place -name 'test_*_blub' | xargs -I % sh -c 'cat %; echo "";'
sh -c 'cat %; echo "";' - multiple commands executed one-by-one
2) with -exec action:
find /my/place -name 'test_*_blub' -exec cat {} \; -exec echo "" \;
3) with -printf action:
find /my/place -name 'test_*_blub' -exec cat {} \; -printf "\n"
Figured out an easy way:
find /my/place -name 'test_*_blub' | xargs cat | xargs -I '{}' echo '{}'

Need help omitting folders in find command

I have this line in a script I'm writing
find / \( -perm -4000 -o -perm -2000 \) -type f -exec file {} \; | grep -v ELF | cut -d":" -f1 >> $OUTPUT
It does the work, BUT I always get these messages I want to omit
find: `/proc/29527/task/29527/fd/5': No such file or directory
find: `/proc/29527/task/29527/fdinfo/5': No such file or directory
find: `/proc/29527/fd/5': No such file or directory
find: `/proc/29527/fdinfo/5': No such file or directory
How can I omit the /proc directory?
I believe this should work:
find / -path /proc -prune -o \( -perm -4000 -o -perm -2000 \) -type f ...
^^^^^^^^^^^^^^^^^^^^^ Add this to your command line
What if you redirect STDERR to /dev/null. That way, you don't see the unwanted error/warning in your TTY (STDOUT) like
{ find / \( -perm -4000 -o -perm -2000 \) -type f -exec file {} \; | grep -v ELF | cut -d":" -f1 >> $OUTPUT; } 2>/dev/null
The following prunes the proc directory:
find / -name /proc -prune -o \
\( -perm -4000 -o -perm -2000 \) -type f \
-exec file {} \; | grep -v ELF | cut -d":" -f1 >> $OUTPUT

xargs on retaining filename for batch html to text conversion

I'm converting some html files to text using html2text and want to retain the name of the file name charliesheenwinning.html as charliesheenwinning.txt or even charliesheenwinning.html.txt .
find ./ -not -regex ".*\(png\|jpg\|gif\)$" -print0 | xargs -0 -L10 {} max-process=0 html2text {} -o ../potistotallywinning/{}.txt
Of course the last part -o is so wrong. How do I retain reusing the filename beyond the first argument to html2text? Can use a for in -exec, but how can I do it with xargs?
update
Ended up doing
find path/to/dir -type f -not -regex ".*\(gif\|png\|jpg\|jpeg\|mov\|pdf\|txt\)$" -print0 | xargs -0 -L10 --max-procs=0 -I {} html2text -o {}.txt {}
mkdir dir/w/textfiles
cp -r path/to/dir dir/w/textfiles
find dir/w/textfiles -type f -not -regex ".*txt$" -print0 | xargs -0 -L10 --max-procs=0 -I {} rm {}
Not the best .. but whatever..
[just in case you were wondering why it isn't just a simple -name '*html' in the find argument, this was a wget of a mediawiki .. ]
You should try to use basename:
$ man basename
I was facing the same problem – for the record, here's what I came up with to get substition into xargs:
seq 100 | xargs -I % -n 1 -P 16 bash -c 'echo % `sed "s/1/X/" <<< %`'
It will print something like this:
10 X0
3 3
12 X2
4 4
11 X1
1 X
15 X5

Bash: how to pipe each result of one command to another

I want to get the total count of the number of lines from all the files returned by the following command:
shell> find . -name *.info
All the .info files are nested in sub-directories so I can't simply do:
shell> wc -l *.info
Am sure this should be in any bash users repertoire, but am stuck!
Thanks
wc -l `find . -name *.info`
If you just want the total, use
wc -l `find . -name *.info` | tail -1
Edit: Piping to xargs also works, and hopefully can avoid the 'command line too long'.
find . -name *.info | xargs wc -l
You can use xargs like so:
find . -name *.info -print0 | xargs -0 cat | wc -l
some googling turns up
find /topleveldirectory/ -type f -exec wc -l {} \; | awk '{total += $1} END{print total}'
which seems to do the trick
#!/bin/bash
# bash 4.0
shopt -s globstar
sum=0
for file in **/*.info
do
if [ -f "$file" ];then
s=$(wc -l< "$file")
sum=$((sum+s))
fi
done
echo "Total: $sum"
find . -name "*.info" -exec wc -l {} \;
Note to self - read the question
find . -name "*.info" -exec cat {} \; | wc -l
# for a speed-up use: find ... -exec ... '{}' + | ...
find . -type f -name "*.info" -exec sed -n '$=' '{}' + | awk '{total += $0} END{print total}'

Resources