1

I have a directory whose name contains spaces. I need to remove the contents of this particular directory. I am escaping spaces in the directory name with \ before removing the contents. The rm command works fine from terminal however it doesn't work if I use it in Shell script. I get No such file or directory error.

For e.g. I have following directory structure Users/Neeraj/Documents/temp dir/dir with spaces/a.txt I need to remove everything inside directory "dir with spaces". The code in my Shell scripts looks like

#!/bin/sh
TEMP_DIR="$HOME/Documents/temp dir/dir with spaces"
TEMP_DIR=$(echo $TEMP_DIR | sed 's/ /\\ /g')
COMMAND="rm -r $TEMP_DIR/*"
echo "Command: $COMMAND"
rm -r "$TEMP_DIR"/*

When I run this script, I get No such file or directory error while the same command works fine if I just copy it and run from the terminal.

Output:

Command: rm -r /Users/Neeraj/Documents/temp\ dir/dir\ with\ spaces/*
rm: /Users/Neeraj/Documents/temp\ dir/dir\ with\ spaces/*: No such file or directory

What is the correct way to do this?

Note: I am using macOS

0

2 Answers 2

2

@Olorins answer is the correct answer to this question, but I want to add some more information why it does not work:


You can use either of these:

rm "dir with spaces"
rm dir\ with\ spaces
dir="dir with spaces"; rm "$dir"

But these won't work:

dir="dir\ with\ spaces";
rm "$dir" # the backslash will be taken literally inside quotes 
rm $dir # this should work, shouldn't it? Please read below.

The latter option was unintuitive for me in the beginning. But bash expands the variable contents, adding some quoting before execution.

You can use set -x to see what gets actually executed:

( var="a\ b"; set -x; echo $var; )
+ echo 'a\' b
a\ b

While the output looks good, the space is still unescaped because the \ is surrounded by single quotes.

1
  • This is an interesting finding. Learnt something new. Thank you for the details. Commented Aug 31, 2018 at 11:01
1

You are using both quotes and backslash-escaping. Using just quoting will work fine.

This should be enough:

TEMP_DIR="$HOME/Documents/temp dir/dir with spaces"
COMMAND="rm -r $TEMP_DIR/*"
echo "Command: $COMMAND"
rm -r "$TEMP_DIR"/*

In this case, both backslashes and quotes are supposed to be handled by the shell, to prevent it from splitting up the directory name. When you use both, the shell preserved both the spaces and the backslashes inside the quotes, so rm actually gets .../temp\ dir/dir\ with\ spaces/... in the arguments where it should have got .../temp dir/dir with spaces/... instead.

When you copy the printed command, the shell sees the backslashes without additional quoting, so it preserves the spaces protected by the backslashes and removes the backslashes, so, rm gets .../temp dir/dir with spaces/... in the arguments.

4
  • Do not use either of them. Use only the one with quotes. The one with backslash-escaping does not work from a variable, because bash will expand the variable before execution.
    – pLumo
    Commented Aug 31, 2018 at 8:20
  • @Olorin My bad, I used both simultaneously which caused the problem. Thank you so much for the detailed explanation. Just using double quotes worked fine. Thanks again. Commented Aug 31, 2018 at 8:23
  • @RoVo You are right. Just using backslash-escaping did not work. Using double quotes is the correct way. Thank you for the solution. Commented Aug 31, 2018 at 8:25
  • @RoVo ah, of course. Corrected.
    – Olorin
    Commented Aug 31, 2018 at 8:28

You must log in to answer this question.

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