I have a probleme to parse the result of my commande :
find / -type f -not \( -path '/dev/*' -or -path '/proc/*' -or -path '/sys/devices/*' \) -print0 |
xargs -0 bash -c 'paste -d " " <(md5sum "$@") <(sha1sum "$@") <(sha256sum "$@") <(du -lh "$@")' bash
which give me this :
c37967f401d16fa37736cbe08809d3d66c8f516a /etc/vmware-tools/resume-vm-default 1aae06b3e3db93584b27ddf24ecd58e7a080f33c160f0186ec9b50ab32bc9a92 /etc/vmware-
tools/resume-vm-default 4.0K /etc/update-manager/release-upgrades
But I don't want spaces to separate them because it's impossible to parse them because of the spaces that appears in the file name.
how can i get something like this?
md5; sha1; sha256, size, path
I don't find how to change the separator between my values.
I tried :
find / -type f -not \( -path '/dev/*' -or -path '/proc/*' -or -path '/sys/devices/*' \) -print0 |
xargs -0 bash -c 'paste -d " " <(md5sum "$@" | printf ";$1;") <(sha1sum "$@" | printf ";$2;") <(sha256sum "$@" | printf ";$3;") <(du -lh "$@" | printf ";$4;")' bash
but it print only the path...
I tried :
find / -type f -not \( -path '/dev/*' -or -path '/proc/*' -or -path '/sys/devices/*' \) -print0 |
xargs -0 bash -c 'paste -d ";" <(md5sum "$@") <(sha1sum "$@") <(sha256sum "$@") <(du -lh "$@")' bash
which is almost why in want. but mistake appears like ^ in my sha1...
Also I don't want to get the file path 5 times.
do did this :
find / -type f -not \( -path '/dev/*' -or -path '/proc/*' -or -path '/sys/devices/*' \) -print0 |
xargs -0 bash -c 'paste -d ";" <(md5sum "$@" | awk "{print $1;}") <(sha1sum "$@" | awk "{print $1;}") <(sha256sum "$@" | awk "{print $1;}") <(du -lh "$@"| awk "{print $1;}")' bash
but it returns a tons of error.
CodePudding user response:
Instead of your complicated use of xargs
and paste
you could use a simpler bash
loop:
$ declare -a r s t u
$ while IFS= read -d '' file; do
r=( $(md5sum "$file") )
s=( $(sha1sum "$file") )
t=( $(sha256sum "$file") )
u=( $(du -lh "$file") )
printf "%s; %s; %s, %s, %s\n" "${r[0]}" "${s[0]}" "${t[0]}" "${u[0]}" "$file"
done < <( find / -type f -not \( -path '/dev/*' -or -path '/proc/*' -or -path '/sys/devices/*' \) -print0 )
The r
, s
, t
and u
indexed arrays are just a way to easily isolate the first word of a command's output.
Note that the output format you chose is probably not that easy to parse because it mixes semi-colons and commas and adds a space after them. Not mentioning the possibility of file names with semi-colons, commas or newlines. A cleaner output format would stick with the NUL separator (the only character that you cannot find in a file name):
$ declare -a r s t u
$ while IFS= read -d '' file; do
r=( $(md5sum "$file") )
s=( $(sha1sum "$file") )
t=( $(sha256sum "$file") )
u=( $(du -lh "$file") )
printf "%s\0%s\0%s\0%s\0%s\0" "${r[0]}" "${s[0]}" "${t[0]}" "${u[0]}" "$file"
done < <( find / -type f -not \( -path '/dev/*' -or -path '/proc/*' -or -path '/sys/devices/*' \) -print0 )
CodePudding user response:
I am not personally fond of long "one-liners" that are hard to read later when you inevitably need to do the same thing again, or maintain/edit it.
while IFS= read -d $'\0' -r filename; do
md5="$(md5sum "$filename")"
sha1="$(sha1sum "$filename")"
sha256="$(sha256sum "$filename")"
durpt="$(du -lh "$filename")"
printf "%s;%s;%s;%s;%s\n" "$filename" "${md5% *}" "${sha1% *}" "${sha256% *}" "${durpt%$'\t'*}"
done < <( find / -type f -not \( -path '/dev/*' -or -path '/proc/*' -or -path '/sys/devices/*' \) -print0 )
This separates the subshell calls out to variable assignments so that formatting and editing them is easier later. I cleaned the filenames &c off the hashes and the end of the du
output, and added the filename as a field at the beginning.