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.

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.]

  • 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 '15 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 '15 at 0:13
  • @Harvey You are correct: I updated the answer to remove that warning. – John1024 Jan 25 '15 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'.

  • 1
    +1 I like your use of xargs -p so much that I will copy it. – John1024 Jan 23 '15 at 7:02
  • 1
    Perfect! And very simple way to make most any command interactive. Thanks. – Harvey Jan 23 '15 at 7:18
  • 21
    Don't parse ls. – Kroltan Jan 23 '15 at 11:51
  • @Kroltan - why would anyone would use a newline in a file name? – nbubis Jan 24 '15 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 '15 at 11:52

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.