Add a newline into a filename with `mv`
Solution 1
It is a bad idea (to have strange characters in file names) but you could do
mv somefile.txt "foo
bar"
(you could also have done mv somefile.txt "$(printf "foo\nbar")"
or mv somefile.txt foo$'\n'bar
, etc... details are specific to your shell. I'm using zsh
)
Read more about globbing, e.g. glob(7). Details could be shell-specific. But understand that /bin/mv
is given (by your shell), via execve(2), an expanded array of arguments: argument expansion and globbing is the responsibility of the invoking shell.
And you could even code a tiny C program to do the same:
#include <stdio.h>
#include <stdlib.h>
int main() {
if (rename ("somefile.txt", "foo\nbar")) {
perror("rename somefile.txt");
exit(EXIT_FAILURE);
};
return 0;
}
Save above program in foo.c
, compile it with gcc -Wall foo.c -o foo
then run ./foo
Likewise, you could code a similar script in Perl, Ruby, Python, Ocaml, etc....
But that is a bad idea. Avoid newlines in filenames (it will confuse the user, and it could break many scripts).
Actually, I even recommend to use only non-accentuated letters, digits, and +-/._%
characters (with /
being the directory separator) in file paths. "Hidden" files (starting with .
) should be used with caution and parcimony. I believe using any kind of space in a file name is a mistake. Use an underscore instead (e.g. foo/bar_bee1.txt
) or a minus (e.g. foo/bar-bee1.txt
)
Solution 2
If you use bash, this command should work.
mv a $'b\nc'
Solution 3
I know you asked for a mv
solution, however, despite the warning, this can be easily done with rename
(in the Perl package):
~/tmp$ touch foo
~/tmp$ rename 's/$/\nbar/' foo
Unsuccessful stat on filename containing newline at /usr/share/perl5/File/Rename.pm line 69.
~/tmp$ ls
foo?bar
Solution 4
One aspect of this problem isn't really about awk
- and only a little bit about the shell. The problem is that on a standard, canonical tty most of the time the kernel's tty discipline is buffering your input - just echoing it to your screen and nowhere else - so that it can efficiently handle backspacing and such-like.
However, when you press return or otherwise enter a newline, all of that buffered data is pushed at once to the reading application - usually your shell. You can observe this by watching for $PS2
after entering a dangling quote. When the shell prints $PS2
it's because its just read some block of your input and is not yet convinced you're through.
So, for convenience, what you need is some way of sending a \n
ewline into the terminal buffer without having to push all of that other input immediately. The standard way to do so is w/ the key-sequence CTRL+V
- which quotes for the terminal your next input character. Do CTRL+V
then CTRL+J
- because the latter is usually how to type a literal \n
ewline. You'll know it's worked when you don't see $PS2
because the shell still hasn't read your input.
Note though that when it does read that input your earlier CTRL+V
will have made no difference for the shell at all - that only quotes it for the line-discipline. You'll definitely want to shell-quote the newline as well to do anything meaningful with it.
By the way, CTRL+V
can be usefully applied in other ways - for example "$(printf \\33)"
is not the only way to write an ESC
character into a shell script - and it isn't even the most simple. You can literally enter any character your keyboard will send without the input driver attempting to interpret it if you just first escape it in this way.
I often like to use <tab>s on the command-line without the shell attempting to complete anything. Because shells which do completion will typically configure <tab> in a way synonymous to stty eol \t
, to make their completion systems work, CTRL+V
works for me even in unfamiliar environments.
Related videos on Youtube
![A.B.](https://i.stack.imgur.com/sirTA.png?s=256&g=1)
A.B.
ZX81, C64, DR-DOS, OS/2, Linux Talk with me in Ask Ubuntu General Room profile for A.B. on Stack Exchange, a network of free, community-driven Q&A sites http://stackexchange.com/users/flair/186154.png
Updated on September 18, 2022Comments
-
A.B. almost 2 years
It's a serious question. I test some
awk
scripts and I need files with a newline in their names.
Is it possible to add a newline into a filename with
mv
?I now, I can do this with
touch
:touch "foo bar"
With touch I added the newline character per copy and paste. But I can't write
foo
Returnbar
in my shell.How can I rename a file, to have a newline in the filename?
Edit 2015/06/28; 07:08 pm
To add a newline in
zsh
I can use, Alt+Return-
Basile Starynkevitch almost 9 yearsWhy do you ask? Are you making some joke or trick to a friend?
-
Basile Starynkevitch almost 9 yearsDon't remove the question, it is useful. But really avoid new lines in filenames as much as possible.
-
Kevin almost 9 yearsWhat makes you think doing it with
mv
would be any different from doing it withtouch
? Did you try the same thing? -
A.B. almost 9 years@Kevin With
touch
I added the newline character per copy and paste. But I can't write "foo<return>bar" in my shell. -
Kevin almost 9 yearsWell, you can copy and paste into the
mv
command just as easily astouch
. -
dan almost 9 yearsWhy are you using copy and paste to type a newline?
-
dan almost 9 yearsI am using
zsh
. I can type"foo [return] bar"
without problem. Please describe what is the problem with the standard [return]. -
A.B. almost 9 years@danielAzuelos That may be, I have used IFS to this day. Thx =)
-
dan almost 9 yearsSo let me suggest you to formulate more clearly your OP: Within a given shell environment I can't type a newline within a quoted string as in echo "a[return]b".
-
luca.vercelli about 4 yearsThis question is indeed very useful. Consider this situation. I have a Python script, and I use it both in Windows and Linux. The script has Windows-ending lines. It begins with "#/usr/bin/env python3\r" and Linux cannot handle that character "\r". So I created a symlink "python3\r" using these suggestions, and now the script is executable under Linux.
-
-
A.B. almost 9 yearsYes, I know, that I can copy and paste a newline character, but how could I do that without copy and paste?
-
dan almost 9 yearsThere isn't any copy or paste here. There is a typed newline after
foo
. -
A.B. almost 9 yearsWorks with
zsh
also =) -
A.B. almost 9 yearsThank you for the
rename
, a very good idea. +1 -
kos almost 9 yearsHowever it works also copy-pasting it
-
artdanil almost 9 yearsIt is a bad idea for usual files, but a good test case, as the OP mentioned.
-
artdanil almost 9 yearsThank you for mentioning 'Ctrl+V'. I was about to post answer about it and then saw your explanation.
-
Stéphane Chazelas almost 9 yearsbash, like zsh and FreeBSD sh copied that from ksh93.
-
Basile Starynkevitch almost 9 yearsOf course
/
is the directory separator -
Basile Starynkevitch almost 9 yearsWhy do you believe
%
is more harmful than@
(which has special meaning, e.g. forscp
)? -
antimirov almost 5 yearsThank you very much! I totally forgot about $ in bash, while it was my own answer on SO advising using it - stackoverflow.com/questions/1825552/grep-a-tab-in-unix/…
-
mekb almost 3 yearsWhy does
''$'\n''
show in ls? -
mekb almost 3 yearsohh the $ denotes escaped characters