0

context: https://stackoverflow.com/a/13941223/15603477
I do understand xargs chmod 755 <file.txt

For bigger amount of files, or almost any number of lines in your input file...

For many binutils tools, like chown, chmod, rm, cp -t ...

xargs chmod 755 <file.txt

If you have special chars and/or a lot of lines in file.txt.

xargs -0 chmod 755 < <(tr \\n \\0 <file.txt)

I not sure (tr \\n \\0 <file.txt) meaning?
In man tr the following is what I found:

\\     backslash        
\n     new line

  
1
  • 2
    Side note: by looking at the title I was like 'why would anyone want \\o in this context?' And then I realized it's this thing again. Oh well. Dec 22, 2021 at 12:26

2 Answers 2

3

\\ represents a backslash, but there's two levels of escaping here.

First, the shell looks at the command line and processes quotes, here, \\n turns into \n. Equally, one could write '\n' or "\n", they'd also produce \n.

Then, tr sees \n and takes it to mean the newline character. Similarly \\0 turns to \0, which means the NUL byte, the one with numerical value zero.

The idea there is to convert the input from one that uses a newline to separate the pathnames, to one that uses the NUL byte to separate them. NUL is a natural separator since it's only character that's invalid in pathnames and also the -0 option to xargs stops it from doing other special processing to the input: by default xargs processes quotes (in its own way, not exactly compatible with the shell's quoting rules), and treats any whitespace as a separator. It's probably better not to use plain xargs.

The -0 option isn't standard, however, but is relatively widely supported. Also, with a conversion like that, you still can't represent filenames that contain newlines, but you can represent everything else, including spaces and quotes.


The <(...) thing is called process substitution, it provides the output of a command to read as if it was a file. It's a sort of a generalization of a pipe, and here, could be replaced with one.

I would write

xargs -0 chmod 755 < <(tr \\n \\0 <file.txt)

as

tr '\n' '\0' <file.txt | xargs -0 chmod 755

(again, \\n = '\n')

2
  • 1
    -0 (from GNU xargs) is not standard but is more widely supported than -d or -a which you could use here as xargs -d '\n' -a file.txt chmod 755 --. Beside that --, you'd likely want to use -r (another GNU extension found in some other implementations, even enabled by default on some BSDs). Dec 22, 2021 at 15:03
  • @ilkkachu can you help me with this
    – jian
    Dec 23, 2021 at 6:59
1

tr \\n \\0 replaces \n (new line) with \0 a NUL character so the content of the file.txt can be passed as null-terminated strings as input to xargs -0, which expected \0 as the line separator. Without -0 xargs expects its input to be separated by spaces and newlines which doesn't work if your file.txt contains spaces.

1
  • It's not only spaces and newlines. Other blank characters, single quotes, double quotes, backslashes, and with some implementations underscores or byte sequences that don't form valid characters would also be a problem. Dec 22, 2021 at 15:05

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .