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

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.

  • This is an interesting finding. Learnt something new. Thank you for the details. – Neeraj Damle Aug 31 '18 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.

  • 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 Aug 31 '18 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. – Neeraj Damle Aug 31 '18 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. – Neeraj Damle Aug 31 '18 at 8:25
  • @RoVo ah, of course. Corrected. – Olorin Aug 31 '18 at 8:28

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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