17

I am trying to delete all the files with a space in their names. I am using following command. But it is giving me an error

Command : ls | egrep '. ' | xargs rm

Here if I am using only ls | egrep '. ' command it is giving me all the file name with spaces in the filenames. But when I am trying to pass the output to rm, all the spaces (leading or trailing) gets deleted. So my command is not getting properly executed.

Any pointers on how to delete the file having atleast one space in their name?

6 Answers 6

32

You can use standard globbing on the rm command:

rm -- *\ *

This will delete any file whose name contains a space; the space is escaped so the shell doesn't interpret it as a separator. Adding -- will avoid problems with filenames starting with dashes (they won’t be interpreted as arguments by rm).

If you want to confirm each file before it’s deleted, add the -i option:

rm -i -- *\ *
2
  • 4
    You will DEFINITELY want to run this through an echo first, to guard from typos. Add echo at the front and it will print out all the files it's going to remove.
    – Riking
    Commented Jun 8, 2015 at 3:00
  • 1
    Anuj, the reason why this has the most upvotes is that because though find is powerful, sometimes you don't need to kill the chicken with a machine gun. UNIX administrators would generally not resort to find to (for example) "remove all files beginning with the letter A"... one would simply rm A*. Likewise to remove files containing spaces, rm can do the job. In other words, don't be fooled because space is invisible and is treated specially by the shell. Simply escape it, as Stephen Kitt has done, and you can think of it like any other character.
    – Mike S
    Commented Jun 8, 2015 at 19:17
23

I would avoid parsing ls output

Why not :

find . -type f -name '* *' -delete

No problem with rm :-).

Although this is recursive and will delete all files with space in current directory and nested directories, as mentionned in comments.

11
  • 5
    (1) you can use -name '* *' instead of the regex; and (2) you can use -print0 | xargs -0 rm -i to address @StephenKitt's concern.
    – Kevin
    Commented Jun 8, 2015 at 5:05
  • 2
    No need for xargs. Just use -exec rm -i '{}' + Commented Jun 8, 2015 at 15:42
  • 1
    @Mhmd It's got more pitfalls than an 8-bit gaming console. mywiki.wooledge.org/ParsingLs
    – Daenyth
    Commented Jun 8, 2015 at 18:22
  • 1
    If you want to avoid subdirectories, use find . -maxdepth 1 -name '* *' -delete.
    – Mikkel
    Commented Jun 8, 2015 at 21:32
  • 1
    @BenjaminW. fixed ?
    – solsTiCe
    Commented Nov 13, 2018 at 11:56
8

Look at this Suppose name "strange file"

Solution one

rm strange\ file

solution two

rm "strange file"

solution three

ls -i "strange file"

you see the inode then

find . -inum "numberoofinode" -exec rm {} \;

In case of very strange file names like

!-filename or --filename

use

rm ./'!-filename'
1
  • Working fine rm "upload/image/catalog/Varanga/WhatsApp Image 2019-12-29 at 9.45.45 PM.jpeg" Commented Jul 15, 2020 at 10:45
5

From man xargs

xargs reads items from the standard input, delimited by blanks (which can be protected with double or single quotes or a backslash) or newlines, and executes the command (default is /bin/echo) one or more times with any initial-arguments followed by items read from standard input. Blank lines on the standard input are ignored.

We can (mostly) fix your initial command by changing the xargs delimiter to a newline:

ls | egrep '. ' | xargs -d '\n' rm (don't do this... read on)

But what if the filename contains a newline?

touch "filename with blanks and newline"

Because Unix filenames can contain blanks and newlines, this default behaviour is often problematic; filenames containing blanks and/or newlines are incorrectly processed by xargs. In these situations it is better to use the -0 option, which prevents such problems.

ls is really a tool for direct consumption by a human, instead we need to use the find command which can separate the filenames with a null character (-print0). We also need to tell grep to use null characters to separate the input (-z) and output (-Z). Finally, we tell xargs to also use null characters (-0)

find . -type f -print0 | egrep '. ' -z -Z | xargs -0 rm

1

You can use:

find . -name '* *' -delete
2
-1

To do it that way, you will need the -Z option of grep, and the -0 option of xargs. But I would not do it that way (ls is not the right tool for the job, there are many problems in getting the computer to read its output).

See other answers for a better way.


Also

ls | … is equivalent to ls -d * and echo * | …

All of which have problems. Therefore don't use ls like this, use a solution from another answer.

2
  • Also ls * when pipes outputs the file names new-line delimited. echo (at least some echo implementations) expands backslash sequences. grep -Z is for writing file names NUL-delimited when using -l, it won't help here. If you meant -z, that won't help either as most ls implementations lack an option to output file names NUL delimited. One could do something like printf '%s\0' * | grep -z ' ' | xargs -r0 rm -f though. Commented Nov 12, 2018 at 17:37
  • 1
    @Kusalananda I think I have fixed it. Commented Nov 13, 2018 at 9:27

You must log in to answer this question.

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