Using zsh, I'd like to create an alias or a shell function that operates as follows:

I want this alias or shell function to echo its command line without honoring any shell control characters such as < or > or & or $ or " or others.

In other words, consider the following example, where I'm using "xxx" as the name of this proposed alias or shell function:

xxx ls -Flastr "${something}" >/tmp/xyz &

It would simply echo the following as follows, without executing it, including the > and & and $ and { and } and ", and without honoring any of those special characters:

ls -Flastr "${something}" >/tmp/xyz &

I know I can do this by quoting the rest of the command line after the "xxx" and possibly escaping certain characters, but I'm looking for a way to make this occur without any extra quoting or escaping.

Also, I want this to be in effect only for the one, single line which is invoked via this alias or shell function, and not for the entire script.

Is this even possible under zsh?

Thank you in advance.

  • Note that none of the special characters mentioned in the question is available to an alias or function. The shell acts upon them before invoking the utility. Could you say more about what the use case is for this?
    – Kusalananda
    Commented Sep 10, 2022 at 18:16
  • I want to use this proposed alias/shell-function to test certain commands. When writing long, complicated script, I might want to see that certain commands are actually going to be executed when the script is running. For example, if the ls ... command that I used an example above appears in a script, I'd like to prefix that command with xxx in the script and run the script to see if that code actually is reached, without it being executed. And I want the rest of the script to indeed be executed.
    – HippoMan
    Commented Sep 10, 2022 at 18:32
  • Also, there is a preexec shell function which receives the entire command before special character substitution. However, that preexec function cannot change the value of the command to be executed. What I want is something like preexec which will also prevent the command from actually being executed
    – HippoMan
    Commented Sep 10, 2022 at 18:35
  • similar (duplicate?): Any shell where expansions are turned off without escaping or quoting? Commented Sep 10, 2022 at 19:54
  • Thank you to Stéphane Chazelas. However, the code in the "Answer" to that question doesn't work for me in the zsh 5.8 under Ubuntu. I used the exact same example that was given in that "Answer", but nothing gets printed at all via that function.
    – HippoMan
    Commented Sep 10, 2022 at 20:09

2 Answers 2


A trick to do this is to write an alias that ends with # to make the rest of the line a comment, then pull the line from the history. Comments must be enabled with setopt interactive_comments. However, it's difficult to know where to start printing. This simple version just prints the whole line.

function xxx_function { print -lr -- ${history[$HISTCMD]}; }
alias xxx='xxx_function #'
  • ... and then someone in a hurry comments out a line that ends with | or \ and then oops
    – thrig
    Commented Sep 10, 2022 at 19:53
  • Thank you for this. But also, $HISTCMD doesn't seem to get set inside of a script.
    – HippoMan
    Commented Sep 10, 2022 at 20:14
  • @thrig The line can end with | or \` without any problems. The #` comments everything until the next newline. Commented Sep 10, 2022 at 21:21
  • @HippoMan Well, sure. This wouldn't make any sense in a script. There you can just edit the lines with the right quotes, or use a here document. Commented Sep 10, 2022 at 21:22
  • no? worst case is something like "echo this is an example of \" followed by "rm -rf /" and then a quick "xxx echo ..." comments out only the echo line and now rm -rf / is (surprise!) no long a continuation and is run. more likely the script hangs because the continuation line is chewing on stdin that is or is not there and oooooh it was due to the stupid xxx trick
    – thrig
    Commented Sep 10, 2022 at 22:09

This is a variation on the suggestion by Stéphane Chazelas, and it works for me. I corrected the original "Answer" here based on the comments, below, by Stéphane Chazelas ...

set -o interactive_comments -o extendedglob
_donothing() {}
alias '@=_donothing # '
handle_@() {
  [[ "${2}" == _donothing ]] && {
    print -r - "${1}"
  return 0
  • Oh! ... not quite. It works if I do this inside of a shell script. But if I put the same code inside of my ~/.zshrc and run a command starting with @ ..., it does things like expanding the variables and aliases, and it honors ` &` at the end of the command.
    – HippoMan
    Commented Sep 10, 2022 at 20:47
  • You're not making use of interactive_comments not extendedglob here.. Even if you meant alias '@=_donothing ', in @ whatever > file the redirection to file would still be performed Commented Sep 10, 2022 at 20:48
  • Yes, I corrected the @=_donothing, above, and the first line of this is indeed using interactive_comments and extendedglob ... ??? Anyway, as I mentioned, this works from inside of a shell script, but not when I put that code into ~/.zshrc.
    – HippoMan
    Commented Sep 10, 2022 at 20:50
  • I mean, you're not using any of the extendedglob operator nor are you commenting out any to prevent it from being run as my answer did. Commented Sep 10, 2022 at 20:52
  • Oh, I see. But then how is it working as written inside of a shell script, but not interactively?
    – HippoMan
    Commented Sep 10, 2022 at 20:55

You must log in to answer this question.

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