24

I am looking for something like:

ls | ask_yes_no_for_each_file | chmod +x the_files_approved

Or similar syntax.

Also could work on other commands that you want individual confirmation for.

2 Answers 2

45

This does what you are looking for:

find . -maxdepth 1 -type f -print0 | xargs -L1 -p0 chmod +x

This uses find rather than ls because, generally, parsing ls output is unreliable. This form, using find, however, will work with filenames even if they contain newlines or other difficult characters.

Explanation

  • find . -maxdepth 1 -type f -print0

    This selects the files. This can be customized using any of find's many options. The option print0 tells find to print the file names in a null-separated list. This is the only reliable to transmit lists of file names.

  • xargs -L1 -p0 chmod +x

    This takes the null-separated list of file names generated by find and applies your command to them.

The -L1 option tells xargs to work on only one file name at a time. The -p option tells xargs to prompt for approval before continuing. The -0 option tells xargs to use the null character as the delimiter between file names.

[I was unaware of the -p option to xargs until @kwan pointed it out.]

3
  • You can make the find command POSIX compatible by using -exec printf '%s\0' {} +. Don't think there's any way to make the whole thing POSIX compatible though.
    – l0b0
    Jan 23, 2015 at 14:25
  • This syntax gives me a warning find: warning: you have specified the -maxdepth option after a non-option argument -type, but options are not positional (-maxdepth affects tests specified before it as well as those specified after it). Please specify options before other arguments. So it works with the -maxdepth 1 before the -type f, as: find . -maxdepth 1 -type f -print0 | xargs -L1 -p0 chmod +x.
    – Harvey
    Jan 25, 2015 at 0:13
  • @Harvey You are correct: I updated the answer to remove that warning.
    – John1024
    Jan 25, 2015 at 1:53
25

You can use xargs.

eg:

ls|xargs -I path -p chmod +x path

Option -p: Prompt the user about whether to run each command line and read a line from the terminal. Only run the command line if the response starts with 'y' or 'Y'.

7
  • 1
    +1 I like your use of xargs -p so much that I will copy it.
    – John1024
    Jan 23, 2015 at 7:02
  • 1
    Perfect! And very simple way to make most any command interactive. Thanks.
    – Harvey
    Jan 23, 2015 at 7:18
  • 21
    Don't parse ls.
    – Kroltan
    Jan 23, 2015 at 11:51
  • @Kroltan - why would anyone would use a newline in a file name?
    – nbubis
    Jan 24, 2015 at 11:25
  • 1
    @nbubis It can happen: go to a terminal and type touch "a very long file name and press enter. See the line continuation and simply type the closing quote and press enter again. tadaa, newline in filename. Out of laziness to retype a long filename.
    – Kroltan
    Jan 24, 2015 at 11:52

You must log in to answer this question.

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