I am having issues getting the pv
command to work with tar
using Bash process substitution.
I can use pv
like this, and it works:
$ tar cvf - dir | pv > file.tar
dir/
dir/b
dir/a
10KiB 0:00:00 [16.9MiB/s] [<=> ]
$ ls -s file.tar
12 file.tar
Using process substitution with cat
also works:
$ tar cvf >(cat > file.tar) dir
dir/
dir/b
dir/a
$ ls -s file.tar
12 file.tar
But this command results in an empty file.tar
:
$ tar cvf >(pv > file.tar) dir
dir/
dir/b
dir/a
$ ls -s file.tar
0 file.tar
I have also tried tar cvf >(pv - > file.tar) dir
with the same result.
My goal is to have pv
print out progress, and pipe the output of tar
(i.e., the list of files and any errors) to other commands for additional processing. The first example command above only results in 2 output streams: stdout
contains the binary tar data, and stderr
contains both the list of files and any error messages. Using process substitution will result in 3 output streams: the binary tar data goes to the new process, stdout
contains the list of files, and stderr
contains any error messages.
Can I use the pv
command with Bash process substitution, and if so, how?
I am using pv 1.6.0
and GNU bash, version 4.3.46(1)-release
.
Interestingly, if I use strace
to try and debug pv
, it works:
$ tar cvf >(strace pv > file.tar) dir
dir/
dir/b
dir/a
execve("/usr/bin/pv", ["pv"], [/* 75 vars */]) = 0
brk(NULL) = 0x1eb8000
access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory)
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f46c9bac000
access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory)
open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=123417, ...}) = 0
mmap(NULL, 123417, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f46c9b8d000
close(3) = 0
access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory)
open("/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0P\t\2\0\0\0\0\0"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0755, st_size=1864888, ...}) = 0
mmap(NULL, 3967392, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7f46c95c0000
mprotect(0x7f46c977f000, 2097152, PROT_NONE) = 0
mmap(0x7f46c997f000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1bf000) = 0x7f46c997f000
mmap(0x7f46c9985000, 14752, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7f46c9985000
close(3) = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f46c9b8c000
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f46c9b8b000
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f46c9b8a000
arch_prctl(ARCH_SET_FS, 0x7f46c9b8b700) = 0
mprotect(0x7f46c997f000, 16384, PROT_READ) = 0
mprotect(0x60d000, 4096, PROT_READ) = 0
mprotect(0x7f46c9bae000, 4096, PROT_READ) = 0
munmap(0x7f46c9b8d000, 123417) = 0
brk(NULL) = 0x1eb8000
brk(0x1ed9000) = 0x1ed9000
fstat(0, {st_mode=S_IFIFO|0600, st_size=0, ...}) = 0
fstat(1, {st_mode=S_IFREG|0644, st_size=0, ...}) = 0
ioctl(2, TCGETS, {B38400 opost isig -icanon -echo ...}) = 0
ioctl(2, TCGETS, {B38400 opost isig -icanon -echo ...}) = 0
ioctl(2, TIOCGWINSZ, {ws_row=73, ws_col=178, ws_xpixel=0, ws_ypixel=0}) = 0
ioctl(2, TCGETS, {B38400 opost isig -icanon -echo ...}) = 0
ioctl(2, TCGETS, {B38400 opost isig -icanon -echo ...}) = 0
ioctl(2, SNDCTL_TMR_START or TCSETS, {B38400 opost isig -icanon -echo ...}) = 0
ioctl(2, TCGETS, {B38400 opost isig -icanon -echo ...}) = 0
rt_sigaction(SIGPIPE, {SIG_IGN, [], SA_RESTORER, 0x7f46c95f54b0}, {SIG_DFL, [], 0}, 8) = 0
rt_sigaction(SIGTTOU, {0x408690, [], SA_RESTORER, 0x7f46c95f54b0}, {SIG_DFL, [], 0}, 8) = 0
rt_sigaction(SIGTSTP, {0x408660, [], SA_RESTORER, 0x7f46c95f54b0}, {SIG_DFL, [], 0}, 8) = 0
rt_sigaction(SIGCONT, {0x408710, [], SA_RESTORER, 0x7f46c95f54b0}, {SIG_DFL, [], 0}, 8) = 0
rt_sigaction(SIGWINCH, {0x408620, [], SA_RESTORER, 0x7f46c95f54b0}, {SIG_DFL, [], 0}, 8) = 0
rt_sigaction(SIGINT, {0x408640, [], SA_RESTORER, 0x7f46c95f54b0}, {SIG_DFL, [], 0}, 8) = 0
rt_sigaction(SIGHUP, {0x408640, [], SA_RESTORER, 0x7f46c95f54b0}, {SIG_DFL, [], 0}, 8) = 0
rt_sigaction(SIGTERM, {0x408640, [], SA_RESTORER, 0x7f46c95f54b0}, {SIG_DFL, [], 0}, 8) = 0
rt_sigaction(SIGSYS, {SIG_IGN, [SYS], SA_RESTORER|SA_RESTART, 0x7f46c95f54b0}, {SIG_DFL, [], 0}, 8) = 0
geteuid() = 4841
stat("/tmp", {st_mode=S_IFDIR|S_ISVTX|0777, st_size=110592, ...}) = 0
msgget(0x500112e9, IPC_CREAT|0600) = 2818048
fstat(0, {st_mode=S_IFIFO|0600, st_size=0, ...}) = 0
fstat(1, {st_mode=S_IFREG|0644, st_size=0, ...}) = 0
ioctl(0, TCGETS, 0x7ffc1cd79860) = -1 ENOTTY (Inappropriate ioctl for device)
fstat(0, {st_mode=S_IFIFO|0600, st_size=0, ...}) = 0
getpid() = 29280
msgrcv(2818048, 0x7ffc1cd797e0, 568, 29280, IPC_NOWAIT) = -1 ENOMSG (No message of desired type)
mmap(NULL, 135168, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f46c9b69000
select(1, [0], [], NULL, {0, 90000}) = 1 (in [0], left {0, 89998})
splice(0, NULL, 1, NULL, 131072, SPLICE_F_MORE) = 10240
select(1, [0], [], NULL, {0, 90000}) = 1 (in [0], left {0, 89999})
splice(0, NULL, 1, NULL, 131072, SPLICE_F_MORE) = 0
read(0, "", 131072) = 0
write(2, " 10KiB 0:00:00 [ 37MiB/s] [ <"..., 178 10KiB 0:00:00 [ 37MiB/s] [ <=> ]) = 178
) = 1
write(2, "\n", 1
) = 1
close(0) = 0
msgctl(2818048, IPC_RMID, 0x7ffc1cd79b30) = 0
ioctl(2, TCGETS, {B38400 opost isig -icanon -echo ...}) = 0
ioctl(2, SNDCTL_TMR_START or TCSETS, {B38400 opost isig -icanon -echo ...}) = 0
ioctl(2, TCGETS, {B38400 opost isig -icanon -echo ...}) = 0
rt_sigaction(SIGPIPE, {SIG_DFL, [], SA_RESTORER, 0x7f46c95f54b0}, NULL, 8) = 0
rt_sigaction(SIGTTOU, {SIG_DFL, [], SA_RESTORER, 0x7f46c95f54b0}, NULL, 8) = 0
rt_sigaction(SIGTSTP, {SIG_DFL, [], SA_RESTORER, 0x7f46c95f54b0}, NULL, 8) = 0
rt_sigaction(SIGCONT, {SIG_DFL, [], SA_RESTORER, 0x7f46c95f54b0}, NULL, 8) = 0
rt_sigaction(SIGWINCH, {SIG_DFL, [], SA_RESTORER, 0x7f46c95f54b0}, NULL, 8) = 0
rt_sigaction(SIGINT, {SIG_DFL, [], SA_RESTORER, 0x7f46c95f54b0}, NULL, 8) = 0
rt_sigaction(SIGHUP, {SIG_DFL, [], SA_RESTORER, 0x7f46c95f54b0}, NULL, 8) = 0
rt_sigaction(SIGTERM, {SIG_DFL, [], SA_RESTORER, 0x7f46c95f54b0}, NULL, 8) = 0
munmap(0x7f46c9b69000, 135168) = 0
exit_group(0) = ?
+++ exited with 0 +++
$ ls -s file.tar
12 file.tar