All POSIX sh
implementations set the $PPID
variable to the pid of the parent of the process that executed it, so:
tar -xvf foo.tgz --to-command='
printf "%s\n" "$TAR_SIZE $TAR_REALNAME" >> "$TAR_ARCHIVE.sizes.$PPID"'
Note that that variable doesn't show up in the output of printenv
as it's not exported to the environment (understandably as its value is only valid for the current shell), use the set
command instead of the printenv
command to list all shell variables (which includes a subset of those reported by printenv
excluding the environment variables that cannot be mapped to shell variables).
$ tar cf - /etc/issue | env -i tar -xf - --to-command='set -x; printenv | grep -i pid; set | grep -i pid'
tar: Removing leading `/' from member names
+ printenv
+ grep -i pid
+ set
+ grep -i pid
PPID='27812'
If for some reason, your sh
didn't set the $PPID
variable, you could always do:
sh -c 'TAR_PID=$$ exec tar -xvf "$1" --to-command="$2"' sh foo.tgz '
printf "%s\n" "$TAR_SIZE $TAR_REALNAME" >> "$TAR_ARCHIVE.sizes.$TAR_PID"'
Where, thanks to exec
, it's the same process that runs sh
and then tar
, so we can make its pid ($$
) available in the TAR_PID
environment variable.
Now, since $TAR_ARCHIVE
and $TAR_PID
don't change, there's no need to reopen the file for every file and you can redirect all that output at once and use >
instead of >>
:
sh -c 'exec tar -xvf "$1" --to-command="$2" > "$1.sizes.$$' sh foo.tgz '
printf "%s\n" "$TAR_SIZE $TAR_REALNAME"'
You can also get size and name information using the standard pax
command.
gunzip < foo.tgz | pax -o listopt='%(size)u %(name)s\n'
Though the implementations commonly found on GNU/Linux systems in my experience don't implement that listopt
option.
printenv
in--to-command
and seeing if there's anything relevant there?--to-command=printenv
and--to-command='sh -c printenv'
, both withecho $!
right afterwards, and could not find the mentioned PID anywhere inprintenv
's output