Wednesday, 30 August 2017

Removing files with spaces in their names in Linux (using IFS)

In UNIX it's uncommon to have files with spaces but it can happen. Consider a situation wherein I have a couple of space separated files and I'd like to remove some of them.

[root@pbox test]# ls -l
total 0
drwxr-xr-x. 2 root root 6 Aug 30 14:25 abc
drwxr-xr-x. 2 root root 6 Aug 30 14:25 def
-rw-r--r--. 1 root root 0 Aug 30 14:17 my file 1
-rw-r--r--. 1 root root 0 Aug 30 14:17 my file 2
-rw-r--r--. 1 root root 0 Aug 30 14:17 my file 3
-rw-r--r--. 1 root root 0 Nov  7  2017 my file 4
-rw-r--r--. 1 root root 0 Nov  7  2020 my file 5
-rw-r--r--. 1 root root 0 Nov  7  2017 my file 6
-rw-r--r--. 1 root root 0 Aug 30 14:24 my file 7

I'd like to remove files modified in the month of August.

[root@pbox test]# ls -l |grep -i ^-|grep -i Aug
-rw-r--r--. 1 root root 0 Aug 30 14:17 my file 1
-rw-r--r--. 1 root root 0 Aug 30 14:17 my file 2
-rw-r--r--. 1 root root 0 Aug 30 14:17 my file 3
-rw-r--r--. 1 root root 0 Aug 30 14:24 my file 7


Now if I try to run the for loop to iterate over the required files I get an unexpected result because of the spaces:

[root@pbox test]# for i in $(ls -l |grep -i ^-|grep -i Aug| awk '{print $9, $10, $11}') ; do echo "$file to remove is $i" ; done
 to remove is my
 to remove is file
 to remove is 1
 to remove is my
 to remove is file
 to remove is 2
 to remove is my
 to remove is file
 to remove is 3
 to remove is my
 to remove is file
 to remove is 7


This is because the default input field separator is a space character so whenever the for loop sees a space it treats the following string as a new field.

To fix this we'll modify our input field separator by changing the value of the IFS variable.


[root@pbox test]# IFS=$'\n'
[root@pbox test]# for i in $(ls -l |grep -i ^-|grep -i Aug| awk '{print $9, $10, $11}') ; do echo "$file to remove is $i" ; done
 to remove is my file 1
 to remove is my file 2
 to remove is my file 3
 to remove is my file 7
[root@pbox test]#

Now instead of doing an echo if we'd like to remove the files we could simply type the following:

[root@pbox test]# for i in $(ls -l |grep -i ^-|grep -i Aug| awk '{print $9, $10, $11}') ; do rm $i ; done
rm: remove regular empty file ‘my file 1’? y
rm: remove regular empty file ‘my file 2’? y
rm: remove regular empty file ‘my file 3’? y
rm: remove regular empty file ‘my file 7’? y

And the files are now gone.

[root@pbox test]# ls -ltr
total 0
drwxr-xr-x. 2 root root 6 Aug 30 14:25 def
drwxr-xr-x. 2 root root 6 Aug 30 14:25 abc
-rw-r--r--. 1 root root 0 Nov  7  2017 my file 4
-rw-r--r--. 1 root root 0 Nov  7  2017 my file 6
-rw-r--r--. 1 root root 0 Nov  7  2020 my file 5

No comments:

Post a Comment

Using capture groups in grep in Linux

Introduction Let me start by saying that this article isn't about capture groups in grep per se. What we are going to do here with gr...