I am running under Debian stable, Cinnamon DE and I have some files that I would like to delete with a command line (for now I delete these files with Nemo).

For example, these .txt files begin with '?' in the shell and in Nemo this '?' is replaced by a carriage return:

$@debian: ls
ssolveIncpUL46pK  ?ssolveIncpUL46pK.txt

nemo

I tried:

 rm ?ss*
 rm \?ss*
 rm \ ss*
  • 7
    Most likely, rather than ?, it's a non-printable character that ls renders as ?. What's the output of ls | sed -n l? – Stéphane Chazelas Aug 21 at 16:39
  • what about rm "?FileName" or find . -name "\?*" -exec rm {} \; rm has not regex type – Hossein Vatani Aug 21 at 16:43
  • @HosseinVatani rm does not parse ? or *, but the shell expands these globs before rm executes. – Kevin Kruse Aug 21 at 16:45
  • @ kevin-kruse yes, I meant he should not try to pass regex phrase to rm – Hossein Vatani Aug 21 at 16:49
  • 1
    @StéphaneChazelas Maybe ls -Q would work better in Debian. – Isaac Aug 21 at 18:16
up vote 17 down vote accepted

The character is not a question mark. The ls utility will replace non printable characters with ?. It is further unclear whether the non printable character really is the first character in the filename or whether there may be one or several spaces before that.

Would you want to delete both those files, you could match the "bad part" with * and then specify the rest of the visible filename more closely:

rm -i ./*ssolve*

This would first expand the given pattern to all the filenames matching it, and then rm would remove them. Be more specific and specify a longer part of the filename if there are files that you don't want to delete that matches the above short pattern, e.g. with

rm -i ./*ssolveIncpUL46pK*

This is assuming that you are located in the same directory as the files that you want to delete.

The -i option to rm makes it ask for confirmation before actually deleting anything.

  • 8
    The next question would be: why does *ssolve* match it when ?ss* doesn't? – Stéphane Chazelas Aug 21 at 17:29
  • 4
    @StéphaneChazelas Because ? does not match enough of the "bad part" of the filename. It may have something to do with multi-byte characters? Or it may simply be that there's a space before the non printable character. You're better than me with that sort of thing. – Kusalananda Aug 21 at 17:37
  • We'll probably never know unless the OP posts the output of ls | sed -n l. – Stéphane Chazelas Aug 21 at 18:01
  • Might want to do echo ./*ssolve* before the rm... just in case. – Christopher Schultz Aug 22 at 19:44

The appropriate way to remove these kind of files is by using the inode value of the file.

Use the following command to get inode value

 ls -li 

 12582925 -rw-r--r--  1 root root   646 May 23 02:19 ?ssolveIncpUL46pK.txt

The first field of the longlisted result is inode value.

Then use the find command to delete the file w.r.t inode.

find . -inum 12582925 -exec rm -i {} \;
  • This would be appropriate if no part of the filename could be matched with a filename globbing pattern, and if the find implementation on the system in question supports the nonstandard -inum predicate (which e.g. GNU find does). – Kusalananda Aug 22 at 14:58
  • 4
    This is actually unsafe. More than one file can have the same inode (using hard links). So instead of deleting just the file with the apparent question mark in it, you would be deleting that file and all the other files with the same inode number, in that directory and in any descendent subdirectories. – Flimm Aug 22 at 19:35
  • @Flimm ls -li will tell you whether the file has any hard links. (If the number immediately before root root is 1, then there are no hard links). – craq Aug 23 at 4:21
  • 1
    @craq Actually, I think this may be unsafe even in the case where ls is showing only 1 hard link. This is because two separate files with separate data entries can actually share the same inode number if they are on different mounted filesystems, I think. You should probably use the -x or -xdev option to avoid this (although you still have the problem of the previous comment.) – Flimm Aug 23 at 12:44
  • 1
    @craq What Flimm is getting at is that an inode n may be allocated on several different mounted filesystems, for very different files. Having inode 1234 on one filesystem does not exclude that the same inode, 1234, exists in another. – Kusalananda Aug 24 at 14:58

It is not recommended to use a * to remove files. It could match more than you like.

Being in Debian, the ls (from GNU) command is able to print the values of the files in quoted form[1]:

$ ls -Q
"\nssolve"  "\n\nssolve"  "y"  "z"

Or, even better, list files with quoted names and inodes:

$ ls -iQ
26738692 "\nssolve"  26738737 "\n\nssolve"  26738785 "y"  26738786 "z" 

Then, use rm with the inode number to ensure that only the correct files are removed:

$ find . -xdev -inum 26738737 -exec rm -i {} \;

The call to find is limited to one filesystem (-xdev) to avoid matching a file on other filesystem with the same inode number. Note also that rm is being called with the -i (interactive) option, so it will ask in the command line if each file should be erased.


[1] Note that this do not solve the problem with visually confusing characters like a Cyrillic а ($'\U430') and a Latin a ($'\U61') that look exactly the same but are not. To have a better look at the bytes that a filename is using we need to use an hex viewer;

$ touch а a é $'e\U301' $'\U301'e
$ ls
a  ́e  é  é  а              # what you "see" here depends on your system.

$ printf '<%s>' * | od -An -c
   <   a   >   < 314 201   e   >   <   e 314 201   >   < 303 251
   >   < 320 260   >

Your Answer

 

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

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