3

I have a file that contains a list of files, and I want to perform two commands on each file.

Contents of files.txt:

file1
file2
file3

The commands I want to perform on each file are (for example) ls -s and du.

I want the output to end up being like this:

<ls size> <du size> file1
<ls size> <du size> file2
<ls size> <du size> file3

I know how to do this using a bash script, but is there a way to easily do this on one line, using process substitution or something?

I thought I could do something like this, but it didn't work:

cat files.txt | tr '\n' '\0' | xargs -0 -I{} cat <(du {} ) <(ls -s {})

That came up with these errors:

du: cannot access `{}': No such file or directory
ls: cannot access {}: No such file or directory

Is there a way to do this?

localhost
  • 1,253
  • 4
  • 18
  • 29

1 Answers1

3

You can run a sh with xargs, in which you can put multiple commands, for example:

xargs -0 -I{} sh -c 'du {}; ls -s {}'
janos
  • 120,954
  • 29
  • 226
  • 236
  • Thanks! OK, my follow-up question is, I want to get `du` to only prefix the line with it's measured size. The usual way is to do `du | cut -f1 | tr --delete '\n'`, but I can't use the single quotes because the `sh` command is quoted using single quotes. Is there any way to substitute all that for the `du` part? – localhost Oct 30 '16 at 12:19
  • You can quote with double-quotes. – janos Oct 30 '16 at 12:20
  • Is there a way to escape it so the filenames can contain either single or double quotes? – localhost May 06 '20 at 14:00
  • @localhost Yes, using a wrapper script, instead of `sh -c '...'`. For example `xargs -0 -I{} wrapper.sh {}`. In this form the shell will correctly escape the filename in `{}`, and `wrapper.sh` can work with `"$1"`, as in `du "$1"; ls -s "$1"` – janos May 07 '20 at 07:38