5

I know that \ is an escape character, but when I write \ in bash, I have something like this:

System-Product-Name:~$ \
> 

So bash waits for some instructions? When I use

System-Product-Name:~$ \
> ls

It is working. But when I use

System-Product-Name:~$ cd Wideo \
> ls
bash: cd: too many arguments

So backslash is working like a pipe | ? I don't think so.

And when I use this command:

find . -name "FILENAME"  -exec rm {} \;

Why do I need to terminate it? I thought that the command find finds proper files and in exec removes them from the path where it found them. Without that, I have information that -exec doesn't have any arguments, I don't get it. Why I can't just use

find . -name "FILENAME"  -exec rm {}

?

I have only that information about exec in man find:

exec Show diagnostic information relating to -exec, -execdir, -ok and -okdir

So why do I need to terminate when I use exec? For example when I use

find . -name "FILENAME"

I don't need to terminate.

1

3 Answers 3

14

You should distinguish the \ at the end of a line which means "this isn't the end of the line, the line continues on the next one" (then your cd command has 2 arguments, too much), and the \ inside a line which prevents the next character from having a special meaning.

Then, \; in your example means give find a literal ; as an argument. Without \, the ; will have its special meaning to the shell, and will work as a separator between the find command and a next one.

The ; argument is needed when you use find with an -exec option so that find knows where the command given with -exec ends. Another alternative is the two arguments {} and +. You should read the find(1) manual for more information.

14
  • 18
    Arguably, the backslash at the end of the line has exactly the same meaning as the backslash inside the line, they both remove the special meaning of the next character (the newline character, and the ; character, respectively). The two cases need not be separated or distinguished from each other.
    – Kusalananda
    Apr 18 at 14:34
  • 7
    If you type echo a\<newline>b the newline is suppressed not given to echo unchanged. Unlike a \ before an other char. I think it would be better to explain 2 cases instead of one. Apr 18 at 14:56
  • 2
    @Kusalananda, compare backslash-newline vs. quote-newline-quote and backslash-semicolon vs. quote-semicolon-quote (with either double or single quotes here)
    – ilkkachu
    Apr 18 at 15:16
  • 8
    @Kusalananda, yes, backslash removes the special meaning of the following character, like quotes do. But if the following character is a newline, it removes the whole character, instead of leaving it as a literal, like quotes do, and like the backslash does to other special characters. E.g. echo :<backslash><newline>:<newline> prints back-to-back colons, while echo :"<newline>":<newline> prints two colons with a newline in between.
    – ilkkachu
    Apr 18 at 19:43
  • 2
    @Kusalananda, no, they nor I don't agree with you on that, backslash in front of newline removes that newline while for any other character, it's a quoting operator \; is like ';' or ";", \<newline> is not like '<newline>'. So saying it has the very same meaning is misleading it's like saying backslash removes its special meaning to n when it changes \n to newline in fish or es. Also note that \<newline> is also removed within double quotes or here documents with unquoted delimiter (inside which newline doesn't have a special meaning) or arithmetic expressions. Apr 19 at 5:29
4

The \ character used in this way is usually referred to as "escapeing" the next character so that bash will remove any special meaning for the character that follows and instead treat it as a literal character rather than process it as part of the bash command line. See https://stackoverflow.com/a/3871336/1663987 for a reference to the bash manual and additional info.

So for

find . -name "FILENAME"  -exec rm {} \;

it tells bash to insert a literal semicolon into the find command arguments rather than process that as a separator between bash commands (ala echo hello; echo world)

For

ls some\ file

it tells bash to treat the space as part of the filename rather than as the character that separates arguments to ls. Thus, it will show ls output for the single file named "some file" (and not two different files named "some" and "file" as it would if just ls some file was used).

For

cd Wideo \
> ls

it telling bash to continue looking for arguments rather than processing the newline as the end of a command, so that the command ends up being processed like cd Wideo ls. This effect is usually referred to as line continuation.

5
  • 3
    But in the case of newline, it also removes the character. If you do cd Wideo\<newline>ls it will be equivalent to cd Wideols. That's why you have to put a space before the backslash.
    – Barmar
    Apr 19 at 15:48
  • 1
    @Barmar Completely agree, but it is probably better for general understanding to note that technically in the case of \ at the end of the line, it is telling bash to remove the special meaning of the newline that follows (i.e. end of a command; process this input), with the effective result that it allows you to continue the command on the next line. That way, input like ls Wideo\ \<newline>ls<newline> makes it clear why the command is interpreted as trying to ls the file Wideo ls (with a space part of the name) since both the space and newline no longer have their bash special meaning.
    – simpleuser
    Apr 19 at 16:49
  • The point is that all the other uses of backslash make the next character literal. Backslash-newline doesn't result in a literal newline, it results in nothing.
    – Barmar
    Apr 19 at 17:32
  • I generally agree, except that is not true within quotes and therefore is not an absolute statement. echo "\d\z\k" outputs \d\z\k because those characters have no special meaning to bash inside quoted strings, unlike \f (formfeed), \n (newline), and a few others.
    – simpleuser
    Apr 19 at 21:31
  • \f and \n have no special meaning in a quoted string, either. But yes, backslash behaves differently inside quotes, it's literal unless it's before something that needs to be escaped.
    – Barmar
    Apr 19 at 21:33
0

"In bash", it's escaping your newline. In find, it's escaping ;.

Normally, when you type Enter, the shell will read that as the end of the command. If you put \Enter it will interpret that as literally a new line.

The second part of the puzzle here is to realize that commands and arguments can contain newlines. There's no rule saying they can't. Most people just avoid using them because they are inconvenient.

However, the following is a valid filename and a valid argument to ls, cd and others:

foo
bar

You can't just type

cd foo
bar

in your shell, because it will try to cd foo and then run bar. But you should be able to do

cd 'foo
bar'

With find, you have a syntax like find -exec some_command. Since some_command can contain spaces, find will look for ; to figure out where the command ends. If you just type find -exec bar ;, bash will treat ; as the end of the find invocation, so it will only pass -exec bar to find.

You need to tell the shell that you mean a literal character ;. You can do this with \;, also with find -exec bar ';'. man find says:

All following arguments to find are taken to be arguments to the command until an argument consisting of ';' is encountered.

Meaning that an argument ; must follow the command of -exec.

2
  • 1
    Read the conversation with other answer. « Escaping newline » would mean the newline is not interpreted by the shell but simply given to the command. This is not the case: the newline is suppressed when prefixed by a \. Type echo a\<newline>b the result is ab not a<newline>b. Then <newline> is not escaped. Apr 19 at 9:47
  • It is obvious what is meant in the answer. Apr 21 at 22:50

You must log in to answer this question.

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