0

I was writing a file management program in C and accidentally created two files that I can't delete.

File 1: ''$'\n'

File 2: 'b.txt'$'\n'

Typing rm and hitting tab twice doesn't even display them.

How do I delete them?

Edit:

Output of ls -la:

-rw-r--r-- 1 pi pi 0 Feb 7 04:12 ''$'\n'
-rw-r--r-- 1 pi pi 0 Feb 7 00:48 'b.txt'$'\n'
6
  • Please edit your question and post the output of ls -la on the relevant directory. Are the single quotes part of the file name?
    – terdon
    Feb 8, 2021 at 20:53
  • see unix.stackexchange.com/questions/451810/… for detailed answer. if there isn't too many files in directory you can use rm -i (see man page)
    – Archemar
    Feb 8, 2021 at 21:05
  • @terdon Post edited. Don't believe they're part of the file name.
    – Anthony
    Feb 8, 2021 at 21:09
  • @Archemar There are quite a few files, so I'd rather avoid deleting the entire directory if possible. Though I suppose I could copy all other files out before doing so. I wouldn't want to do that every single time I accidentally create a file like this, though.
    – Anthony
    Feb 8, 2021 at 21:10
  • Finding their inode with ls -i and using find would be an option. Feb 8, 2021 at 21:11

2 Answers 2

4

That should probably be 'b.txt'$'\n' in the latter, with the final single quote.

That looks like the output of GNU ls with the quoting style shell-escape. Recent versions of GNU ls use some such quoting by default. You can verify it's that by running ls -l --quoting-style=shell-escape to see if that gives the same output. As the name says, the output is quoted like the shell does it, so it can be used as input to the shell. Hence, it should be possible to remove either or both files by just copypasting the quoted/escaped output from ls to Bash:

ls -l ''$'\n' 'b.txt'$'\n

and then of course rm ... after you verify you got the right files.

For what it's worth, the first filename is just a lone newline (for some reason the escaping adds the leading empty ''), the second is b.txt and a newline at the end.

2
  • Using find on their inode number seemed to show them as ? and b.txt?, so I assume that ? is the newline?
    – Anthony
    Feb 8, 2021 at 21:16
  • @Anthony the man page for GNU find says that for -print (the default action), the filename is quoted "in the same way as for GNU ls" (when printed to a terminal), so perhaps it indeed changes nonprintable characters to ?s. That's what ls does too, with other quoting style settings.
    – ilkkachu
    Feb 8, 2021 at 21:21
0

Enter "rm filename as displayed by ls" to remove files, e.g.

rm ''$'\n'

Background:

  1. Your filenames got a newline character appended (or, in case of ''$'\n', even consist only of a single newline character)
  2. Enter ls -N to get a different (the traditional) view
  3. Regarding $'\n', which represents the newline character, see "ANSI-C Quoting" (http://www.gnu.org/software/bash/manual/html_node/ANSI_002dC-Quoting.html)
  4. Regarding different output formats of ls, see "GNU Coreutils - Quoting File names" (https://www.gnu.org/software/coreutils/quotes.html), or man page ls(1) (man 1 ls) - look for "quoting"
  5. It seems, shell tab completion cannot handle filenames containing a newline character properly, and especially ''$'\n'
  6. Filenames starting with a new line character are treated specially by ls by prepending two single quotes - might be a bug
1
  • Bash at least can tab-complete filenames with newlines just fine, though with the filename only containing the newline, it's hard to do since you don't have anything to start the tab-completion. (Unless it's the only file in the directory.) The bash-completion scripts, on the other hand, are probably totally incapable of dealing with newlines.
    – ilkkachu
    Feb 9, 2021 at 0:02

You must log in to answer this question.

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