Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

I somehow managed to create a file that doesn't seem to have a filename. I found some information regarding how to get more details of the file in the following thread.

However, I tried some of the suggestions listed and can't seem to delete the file. I'm not sure what I did to create it, but it happened while trying to copy an xml file. Any ideas are appreciated.

Some info on the file is as follows;

> ls -lb
total 296
-rw-r--r--   1 voyager  endeavor  137627 Jan 12 12:49 \177

> file *
:               XML document

> ls -i
 417777   

I tried to find using the inum switch and then pipe that to rm as that seemed like the most foolproof way of getting rid of it. However, the example given at the bottom of the thread linked below failed for me. Example was;

> find -inum 41777 -exec ls -al {} \;
find: illegal option -- i
find: [-H | -L] path-list predicate-list

so I tried using the path list first like the following, but that didn't work either;

> find . -inum 41777 -exec ls -al {} \;

Any help on how to remove this file is appreciated. I'm not sure what the non-printable character \177 is or how I can pass that to an rm command, but I really want to make sure I don't mess up any other files/directories in my attempt to delete this file.

Thanks.

share|improve this question
    
\177 is the ASCII DEL character. –  Keith Thompson Jan 13 '12 at 1:57
3  
417777 != 41777 –  Michael Kjörling Jan 13 '12 at 9:22
    
Excellent point Michael. That is probably why my command never worked. –  Mr Moose Jan 13 '12 at 15:33
add comment

9 Answers

up vote 25 down vote accepted

The file has a name, but it's made of non-printable characters. If you use bash, you can try to remove it by specifying its non-printable name. First ensure that the name is right with: ls -l $'\177' If it shows the right file, then use rm: rm $'\177'

Another (a bit more risky) approach is to use rm -i -- * . With the -i option rm requires confirmation before removing a file, so you can skip all files you want to keep but the one.

Good luck!

share|improve this answer
    
This worked a treat. Thanks heaps! –  Mr Moose Jan 13 '12 at 3:15
1  
I suspect that rm -i * wouldn't have worked in this case; because of the newlines, the shell would expand * to something that rm wouldn't recognize as the file name. –  Keith Thompson Jan 13 '12 at 5:32
3  
@KeithThompson: Glob expansion in the shell isn't subject to further interpretation. There wouldn't be a newline in the expanded name unless it contained one. –  Christoffer Hammarström Jan 13 '12 at 11:25
    
@ChristofferHammarström: Hmm. I'll do some experiments and comment further. –  Keith Thompson Jan 13 '12 at 19:05
    
@ChristofferHammarström: There's a newline in the expanded name because the file name contains newline characters. But it seems I've underestimated bash and GNU rm. On my system, rm *, rm -i *, and rm Ctrl-V DEL TAB ENTER all work correctly, even if the file name contains a newline character (I used "\177foo\nbar\n"). Some commands don't handle such file names well, but the GNU tools seem robust; non-GNU versions of the same tools might not behave as well. In any case, the various tricks in these answers are useful to know. –  Keith Thompson Jan 13 '12 at 20:29
add comment

The other answers are great and will work in almost all environments.

But, if you happen to have a gui running, just open the directory in nautilus, dolphin, konqueror, or your favorite file manager and you should be able to easily see and delete any file that has an uncooperative name with a couple of mouse clicks.

If you're not a regular emacs or vim user (as featured in several other answers), this might be the easiest way to go.

share|improve this answer
add comment

The file actually has a name, but it's made of non-printable characters.

An easy method is to rely on shell completion: press Tab repeatedly until the “strange” file name is inserted. You must have your shell configured to cycle between possible completions:

  • In bash, you need to invoke menu-complete, which is not bound by default, rather than complete, which is bound to Tab by default. Alternatively, use Esc * to insert completions for all files, and remove the ones you don't want to delete from the command line.
  • In zsh, the default settings are fine; you need to have setopt auto_menu or setopt menu_complete set.

If completion isn't helpful in your shell, you can call rm -i -- * and answer “no” except for this particular file. If the file's name doesn't begin with a printable character, you can restrict the matches to files whose first character isn't in a set of printable characters:

rm -i [!!-~]*
rm -i [![:print:]]*
rm -i -- [!a-z]

(Beware if your pattern may match a file called -f, which rm would treat as an option.)

Another method is to call ls -i to find the file's inode (an inode uniquely identifies a file on a given filesystem), then find -inum to operate on that particular file. This method is mostly useful when the directory contains a lot of files.

ls -i
# note the inode number 12345
find . -xdev -inum 12345 -delete

If your find doesn't have a -delete option, call rm:

find . -xdev -inum 12345 -exec rm -- {} \;

(Yes, I know that most of this has already been posted. But the answers with the relevant information are making this more complicated than it should be.)

share|improve this answer
add comment

I can just about guarantee you that the file does have a name. It just happens to be a name that contains non-printable characters.

If rm didn't work, then using the output of find with the -inum option as an argument to rm isn't likely to help; it's just going to pass the same argument to rm, with the same problem.

The file is the only one in that directory, right?

The first thing I'd try is to cd into the directory, then type rm ./, then hit the Tab key. This should expand the argument to the actual name of the file, and the preceding ./ should prevent rm from interpreting the argument as something other than a file name.

Another solution is to cd to the parent directory, then use rm -r (or, if necessary, rm -rf) on the directory. That should remove the directory and all its contents, regardless of name. You can then use mkdir to recreate the directory (and perhaps chmod to restore its permissions).

EDIT :

Looking at your ls -lb output again, I think that the file name starts with an ASCII DEL character (which is bad not not fatal) and contains one or more newline characters (which is really bad). As far as I can tell, the rm command can't interpret a newline as part of a file name.

But the unlink() system call can. Here's a Perl script I threw together that will iterate through the files in the current directory, and ask you for each one whether you want to remove it. It doesn't use an external command like rm to remove the files, so it should be able to handle any funny characters that the file system supports (anything other than ASCII NUL and /).

Doing rm -r or rm -rf on the containing directory should still work, but if you just want to remove a single file you can try this.

#!/usr/bin/perl

use strict;
use warnings;

opendir my $DIR, '.' or die ".: $!\n";
my @files = sort grep { -f } readdir $DIR;
closedir $DIR;

foreach my $file (@files) {
    my $pfile = printable($file);
    print "Remove $pfile? ";
    my $answer = scalar <STDIN>;
    if ($answer =~ /^[Yy]/) {
        print "Removing $pfile\n";
        unlink $file or warn "Unable to remove $pfile: $!\n";
    }
}

sub printable {
    my($s) = @_;
    $s =~ s/[^ -~]/?/g;
    return $s;
}

(Another solution, if there are other files in the directory that you want to keep, is to move all the other files into a temporary directory, then nuke and recreate the directory and move the other files back.)

(Oh, and whatever you did to create that file, try not to do it again!)

share|improve this answer
    
Thanks for all your efforts. I tried some of the other solutions first before getting to yours and managed to get it solved already. Thanks again though. –  Mr Moose Jan 13 '12 at 3:16
add comment

Try using echo -e to get the character \177, then xargs to pass it to rm. echo doesn't take decimal escapes, so convert to hex: Turns out the 177 is octal; echo requires a \0 (literal, not null byte) before:

echo -ne '\0177\0' | xargs -0 rm
share|improve this answer
    
Are you saying that \xb1\0 is the hex representation of \177? –  Mr Moose Jan 13 '12 at 1:57
    
@MrMoose \xb1 is decimal 177, \0 null-terminates it, and -0 tells xargs to take a null-terminated name instead of a newline-terminated one. –  Kevin Jan 13 '12 at 2:02
    
I'm using bash on SunOS and when I tried your command, I got xargs: illegal option -- 0. I looked at the man page and couldn't see an option for null termination. I managed to get a fix for the issue now though. See the response marked as answer. –  Mr Moose Jan 13 '12 at 3:18
    
Your echo, as-is, sends 2 file names to xargs, and then on to rm... the second file name is \n.. This results in either an error, or deleting a file of that name ('\n') –  Peter.O Jan 13 '12 at 3:29
    
@perer Yes, I just noticed that. I added -n to get rid of the newline. –  Kevin Jan 13 '12 at 3:34
show 3 more comments

You have already demonstrated with file * that the shell glob (*) is able to pick up this file, so now just do an rm on that glob.

  • Change to the directory the file is in.
  • Run rm -i *
  • Enter n for all the files except for the one with the seemingly invisible file name
share|improve this answer
    
interactive rm! that is a great idea. I should have tried that. –  Mr Moose Jan 13 '12 at 3:24
add comment

If you can find exactly that file using find command, then you can use -delete predicate. Just be careful, and make -delete a last parameter of find command or it will hurt a lot...

share|improve this answer
add comment

For those who use vim run it in the current working directory:

$ vim ./ 

and navigate to the file with the arrow keys or j/k. Then hit Shift+D and confirm deletion with y.

share|improve this answer
    
Nice workaround! Easy to remember too! –  phunehehe Jan 13 '12 at 12:00
add comment

There's probably a way to pass the filename to rm, but if you're worried about messing anything up you can use a GUI file manager. Emacs comes with a directory editing mode you can use if you have it installed:

  1. Open the folder in emacs. You can run emacs /path/to/folder, or open emacs, hit Esc+x, and run dired, which will prompt for the path

  2. Move to the row with the file you want to delete and press d. You should see a D in the left margin next to the file:

  3. Press x to save your changes. It'll prompt to make sure you want to delete the file; press y:

share|improve this answer
2  
Nice nyan cat. :) –  Kevin Jan 13 '12 at 1:52
    
Looks like a great idea, but I can't seem to find emacs on this machine. At the risk of starting a holy war...can this be done in vim? –  Mr Moose Jan 13 '12 at 1:57
2  
For those who use vim run it in the current working directory: vim ./ and navigate to the file with the arrow keys. Then hit Shift+D and confirm deletion with y. –  Herman Torjussen Jan 13 '12 at 2:01
    
@hesse Wow. Not something I would've expected vim to support –  Michael Mrozek Jan 13 '12 at 2:02
1  
@Kevin nyan mode: nyan-mode.buildsomethingamazing.com –  Tim Jan 13 '12 at 11:09
show 3 more comments

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.