Emacs/emacs/Shell-Commands-in-Dired

From Get docs

30.8 Shell Commands in Dired

The Dired command ! (dired-do-shell-command) reads a shell command string in the minibuffer, and runs that shell command on one or more files. The files that the shell command operates on are determined in the usual way for Dired commands (see Operating on Files). The command X is a synonym for !.

The command & (dired-do-async-shell-command) does the same, except that it runs the shell command asynchronously. (You can also do this with !, by appending a ‘&’ character to the end of the shell command.) When the command operates on more than one file, it runs multiple parallel copies of the specified shell command, one for each file. As an exception, if the specified shell command ends in ‘;’ or ‘;&’, the shell command is run in the background on each file sequentially; Emacs waits for each invoked shell command to terminate before running the next one.

For both ! and &, the working directory for the shell command is the top-level directory of the Dired buffer.

If you tell ! or & to operate on more than one file, the shell command string determines how those files are passed to the shell command:

  • If you use ‘*’ surrounded by whitespace in the command string, then the command runs just once, with the list of file names substituted for the ‘*’. The order of file names is the order of appearance in the Dired buffer.

    Thus, ! tar cf foo.tar * RET runs tar on the entire list of file names, putting them into one tar file foo.tar.

    If you want to use ‘*’ as a shell wildcard with whitespace around it, write ‘*""’. In the shell, this is equivalent to ‘*’; but since the ‘*’ is not surrounded by whitespace, Dired does not treat it specially.

  • Otherwise, if the command string contains ‘?’ surrounded by whitespace or ‘`?`’, Emacs runs the shell command once for each file, substituting the current file name for ‘?’ and ‘`?`’ each time. You can use both ‘?’ and ‘`?`’ more than once in the command; the same file name replaces each occurrence. If you mix them with ‘*’ the command signals an error.
  • If the command string contains neither ‘*’ nor ‘?’ nor ‘`?`’, Emacs runs the shell command once for each file, adding the file name at the end. For example, ! uudecode RET runs uudecode on each file.

To iterate over the file names in a more complicated fashion, you might prefer to use an explicit shell loop. For example, here is how to uuencode each file, making the output file name by appending ‘.uu’ to the input file name:

for file in * ; do uuencode "$file" "$file" >"$file".uu; done

The same example with ‘`?`’ notation:

uuencode ? ? > `?`.uu

The ! and & commands do not attempt to update the Dired buffer to show new or modified files, because they don’t know what files will be changed. Use the g command to update the Dired buffer (see Dired Updating).

See Single Shell, for information about running shell commands outside Dired.