Expand or grow a file system on a Linux VMWare VM without downtime

When your VM’s file systems are running out of space and you want to provide more space to your VM and you can’t afford any downtime, there are basically two options. Either you delete some files on the file system or you expand your current file system. Expanding your current file system can be accomplished by growing an existing virtual disk or adding a new virtual disk. Besides cleaning up, both other solutions work fine and I’ll try to explain how to get both of them active without rebooting the system or any downtime.

Available free space should be monitored at all times since a system really behaves unpredictable when there is no more free space on an (important) file system. When you see that a file system is filling up, you can’t keep deleting stuff since there is a reason that the storage is used.

To have the flexibility to dynamically grow or shrink file systems, you need to use LVM. The Logical Volume Manager adds an extra “virtual” layer above your real block devices which adds a lot of flexibility. When using virtual machines, that real block device is in fact also a virtual device. For the rest of this post, I assume you know what LVM is and how to use it. If not, take a look here.

Option 1: Add a new virtual disk to the VM

The first possible way to expand your storage online, is to add a new virtual disk to your running system. This is the only option when using VMWare Player. While this option is easier since it doesn’t involve trouble with the MBR-limitations, it’s less clean if you want to add space on a regular basis since your VM ends up with a lot of virtual disk drives and VMDK-files.

Our example machine has a virtual disk of only 5GB and before expanding the file system we can see that it’s running out of space in the /home filesystem:

[root@cen ~]# df -h
Filesystem                  Size  Used Avail Use% Mounted on
/dev/mapper/vg_sys-lv_root  2.0G  740M  1.3G  37% /
devtmpfs                    994M     0  994M   0% /dev
tmpfs                      1000M     0 1000M   0% /dev/shm
tmpfs                      1000M  8.4M  992M   1% /run
tmpfs                      1000M     0 1000M   0% /sys/fs/cgroup
/dev/mapper/vg_sys-lv_home  509M  509M   20K 100% /home
/dev/mapper/vg_sys-lv_tmp   509M   26M  483M   6% /tmp
/dev/mapper/vg_sys-lv_var   1.4G  121M  1.3G   9% /var
/dev/sda1                    97M   65M   33M  67% /boot

The /home filesystem is on a logical volume, so let’s check if the volume group for that volume still has some free space:

[root@cen ~]# vgdisplay
  --- Volume group ---
  VG Name               vg_sys
  System ID
  Format                lvm2
  Metadata Areas        2
  Metadata Sequence No  7
  VG Access             read/write
  VG Status             resizable
  MAX LV                0
  Cur LV                5
  Open LV               5
  Max PV                0
  Cur PV                1
  Act PV                1
  VG Size               4.88 GiB
  PE Size               32.00 MiB
  Total PE              156
  Alloc PE / Size       156 / 4.88 GiB
  Free  PE / Size       0 / 0 GiB
  VG UUID               pzPaBt-ylaD-olYT-8H5w-jODd-8hTY-bglG3y

As you can see, there are no more free extents in the volume group so we can’t simply expand the logical volume for /home.

Add a new virtual disk with the Vsphere Client

The first step for option 1, to resolve our problem, is to add a new virtual disk to the guest that is running out of space. This can be done via the Vsphere Client, the Vsphere Web-client, the API,…

In the vSphere client, right click on the VM that’s running out of space and click “Edit Settings…”:

vmware_editsettings

In the “Virtual Machine Properties”, click on “Add…” and select “Hard Disk” from the list.

vmware_adddisk1

Click “Next >” and choose the size for the new disk, then continue.

vmware_adddisk2

As you can see in the above screenshot, a new virtual disk of 5GB was added to the system.

The same process can be done with VMWare Player in a similar way

Use the newly added disk to extend an existing Volume Group

After adding the new disk to the VM, we can start using it. The first step is to check which name our newly added disk has.

[root@cen ~]# tail -15 /var/log/messages
Jan  7 17:39:38 cen systemd-logind: New session 1 of user root.
Jan  7 17:47:50 cen kernel: vmw_pvscsi: msg type: 0x0 - MSG RING: 1/0 (5)
Jan  7 17:47:50 cen kernel: vmw_pvscsi: msg: device added at scsi0:1:0
Jan  7 17:47:50 cen kernel: scsi 0:0:1:0: Direct-Access     VMware   Virtual disk     1.0  PQ: 0 ANSI: 2
Jan  7 17:47:50 cen kernel: sd 0:0:1:0: Attached scsi generic sg2 type 0
Jan  7 17:47:50 cen kernel: sd 0:0:1:0: [sdb] 10485760 512-byte logical blocks: (5.36 GB/5.00 GiB)
Jan  7 17:47:50 cen kernel: sd 0:0:1:0: [sdb] Write Protect is off
Jan  7 17:47:50 cen kernel: sd 0:0:1:0: [sdb] Cache data unavailable
Jan  7 17:47:50 cen kernel: sd 0:0:1:0: [sdb] Assuming drive cache: write through
Jan  7 17:47:50 cen kernel: sd 0:0:1:0: [sdb] Cache data unavailable
Jan  7 17:47:50 cen kernel: sd 0:0:1:0: [sdb] Assuming drive cache: write through
Jan  7 17:47:50 cen kernel: sdb: unknown partition table
Jan  7 17:47:50 cen kernel: sd 0:0:1:0: [sdb] Cache data unavailable
Jan  7 17:47:50 cen kernel: sd 0:0:1:0: [sdb] Assuming drive cache: write through
Jan  7 17:47:50 cen kernel: sd 0:0:1:0: [sdb] Attached SCSI disk
[root@cen ~]# lsblk
NAME               MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
fd0                  2:0    1    4K  0 disk
sda                  8:0    0    5G  0 disk
├─sda1               8:1    0  100M  0 part /boot
└─sda2               8:2    0  4.9G  0 part
  ├─vg_sys-lv_swap 253:0    0  512M  0 lvm  [SWAP]
  ├─vg_sys-lv_root 253:1    0    2G  0 lvm  /
  ├─vg_sys-lv_var  253:2    0  1.4G  0 lvm  /var
  ├─vg_sys-lv_home 253:3    0  512M  0 lvm  /home
  └─vg_sys-lv_tmp  253:4    0  512M  0 lvm  /tmp
sdb                  8:16   0    5G  0 disk
sr0                 11:0    1  570M  0 rom

As you can see in the last messages in the syslog and in the output of lsblk, we can see that a device, named sdb was added with a size of 5GB.

In case the newly added device isn’t automatically detected, which tends to happen mostly with VMWare Player, you can execute the following to scan for new devices:

[root@cen jensd]# ls /sys/class/scsi_host/ | while read host ; do echo "- - -" > /sys/class/scsi_host/$host/scan ; done

Now that we know the name of our new virtual disk, we need to create a partition on the system before we can use it to expand a currently existing filesystem with LVM. This can be done with fdisk:

[root@cen ~]# fdisk /dev/sdb
Welcome to fdisk (util-linux 2.23.2).

Changes will remain in memory only, until you decide to write them.
Be careful before using the write command.

Device does not contain a recognized partition table
Building a new DOS disklabel with disk identifier 0x271cd89c.

Command (m for help): n
Partition type:
   p   primary (0 primary, 0 extended, 4 free)
   e   extended
Select (default p): p
Partition number (1-4, default 1): 1
First sector (2048-10485759, default 2048):
Using default value 2048
Last sector, +sectors or +size{K,M,G} (2048-10485759, default 10485759):
Using default value 10485759
Partition 1 of type Linux and of size 5 GiB is set

Command (m for help): t
Selected partition 1
Hex code (type L to list all codes): 8e
Changed type of partition 'Linux' to 'Linux LVM'

Command (m for help): p

Disk /dev/sdb: 5368 MB, 5368709120 bytes, 10485760 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk label type: dos
Disk identifier: 0x271cd89c

   Device Boot      Start         End      Blocks   Id  System
/dev/sdb1            2048    10485759     5241856   8e  Linux LVM

Command (m for help): w
The partition table has been altered!

Calling ioctl() to re-read partition table.
Syncing disks.

After adding the partition, which is named sdb1, we can start using it by creating a physical volume for LVM:

[root@cen ~]# pvcreate /dev/sdb1
  Physical volume "/dev/sdb1" successfully created

After creating the physical volume, we can extend the existing volume group, named vg_sys by adding the physical volume to it.

[root@cen ~]# vgextend vg_sys /dev/sdb1
  Volume group "vg_sys" successfully extended
[root@cen ~]# vgdisplay
  --- Volume group ---
  VG Name               vg_sys
  System ID
  Format                lvm2
  Metadata Areas        2
  Metadata Sequence No  7
  VG Access             read/write
  VG Status             resizable
  MAX LV                0
  Cur LV                5
  Open LV               5
  Max PV                0
  Cur PV                2
  Act PV                2
  VG Size               9.84 GiB
  PE Size               32.00 MiB
  Total PE              315
  Alloc PE / Size       156 / 4.88 GiB
  Free  PE / Size       159 / 4.97 GiB
  VG UUID               pzPaBt-ylaD-olYT-8H5w-jODd-8hTY-bglG3y

After adding the physcial volume /dev/sdb1 to volume group vg_sys, you can see that now our volume group has about 5GB of free space. and cosists of two physical volumes.

Time to, finally, extend the logical volume containing /home and grow the filesystem residing on that volume to the size of it.

[root@cen ~]# lvextend -L+2G /dev/vg_sys/lv_home
  Extending logical volume lv_home to 2.50 GiB
  Logical volume lv_home successfully resized
[root@cen ~]# xfs_growfs /dev/vg_sys/lv_home
meta-data=/dev/mapper/vg_sys-lv_home isize=256    agcount=4, agsize=32768 blks
         =                       sectsz=512   attr=2, projid32bit=1
         =                       crc=0
data     =                       bsize=4096   blocks=131072, imaxpct=25
         =                       sunit=0      swidth=0 blks
naming   =version 2              bsize=4096   ascii-ci=0 ftype=0
log      =internal               bsize=4096   blocks=853, version=2
         =                       sectsz=512   sunit=0 blks, lazy-count=1
realtime =none                   extsz=4096   blocks=0, rtextents=0
data blocks changed from 131072 to 655360

The command to expand the filesystem depends on the type of filesystem on it. If you don’t know which filesystem you’re using, you can find the fs type with command df -T.

Now that we expanded logical volume lv_home and the filesystem on it, we’re back in a more comfortable state with some free space on /home.

[root@cen ~]# df -h
Filesystem                  Size  Used Avail Use% Mounted on
/dev/mapper/vg_sys-lv_root  2.0G  740M  1.3G  37% /
devtmpfs                    994M     0  994M   0% /dev
tmpfs                      1000M     0 1000M   0% /dev/shm
tmpfs                      1000M  8.4M  992M   1% /run
tmpfs                      1000M     0 1000M   0% /sys/fs/cgroup
/dev/mapper/vg_sys-lv_home  2.5G  510M  2.0G  20% /home
/dev/mapper/vg_sys-lv_tmp   509M   26M  483M   6% /tmp
/dev/mapper/vg_sys-lv_var   1.4G  121M  1.3G   9% /var
/dev/sda1                    97M   65M   33M  67% /boot

To use the rest of the space in the volume group vg_sys, let’s give it to another logical volume and expand it:

[jensd@cen ~]$ sudo lvextend -l +100%free /dev/vg_sys/lv_tmp
  Extending logical volume lv_tmp to 3.47 GiB
  Logical volume lv_tmp successfully resized
[jensd@cen ~]$ sudo xfs_growfs /dev/vg_sys/lv_tmp
meta-data=/dev/mapper/vg_sys-lv_tmp isize=256    agcount=4, agsize=32768 blks
         =                       sectsz=512   attr=2, projid32bit=1
         =                       crc=0
data     =                       bsize=4096   blocks=131072, imaxpct=25
         =                       sunit=0      swidth=0 blks
naming   =version 2              bsize=4096   ascii-ci=0 ftype=0
log      =internal               bsize=4096   blocks=853, version=2
         =                       sectsz=512   sunit=0 blks, lazy-count=1
realtime =none                   extsz=4096   blocks=0, rtextents=0
data blocks changed from 131072 to 909312
[jensd@cen ~]$ df -h
Filesystem                  Size  Used Avail Use% Mounted on
/dev/mapper/vg_sys-lv_root  2.0G  740M  1.3G  37% /
devtmpfs                    994M     0  994M   0% /dev
tmpfs                      1000M     0 1000M   0% /dev/shm
tmpfs                      1000M  8.4M  992M   1% /run
tmpfs                      1000M     0 1000M   0% /sys/fs/cgroup
/dev/mapper/vg_sys-lv_home  2.5G  510M  2.0G  20% /home
/dev/mapper/vg_sys-lv_tmp   3.5G   27M  3.5G   1% /tmp
/dev/mapper/vg_sys-lv_var   1.4G  122M  1.3G   9% /var
/dev/sda1                    97M   65M   33M  67% /boot

Option 2: Expanding a current virtual disk and use it

While the previous option works well, it could be interesting to expand a current virtual disk instead of adding a new one. This has some limitations when working with MBR since a partition table can only have a maximum of 4 primary partition.

As with option 1, we ran out of space again in the /home filesystem and there’s no more free space in the volume group (we gave it to /tmp):

[jensd@cen ~]$ df -h
Filesystem                  Size  Used Avail Use% Mounted on
/dev/mapper/vg_sys-lv_root  2.0G  740M  1.3G  37% /
devtmpfs                    994M     0  994M   0% /dev
tmpfs                      1000M     0 1000M   0% /dev/shm
tmpfs                      1000M  8.4M  992M   1% /run
tmpfs                      1000M     0 1000M   0% /sys/fs/cgroup
/dev/mapper/vg_sys-lv_home  2.5G  2.5G   20K 100% /home
/dev/mapper/vg_sys-lv_tmp   3.5G   27M  3.5G   1% /tmp
/dev/mapper/vg_sys-lv_var   1.4G  122M  1.3G   9% /var
/dev/sda1                    97M   65M   33M  67% /boot

Expand an existing virtual disk with the Vsphere client

Similar as to add a new disk by changing the VM’s settings with the VMWare client, we can enlarge the existing first disk.

In the vSphere client, right click on the VM that’s running out of space and click “Edit Settings…”:

vmware_editsettings

Select the first disk (known on the system as /dev/sda):

vmware_expanddisk1

Simply increase the size in the right side of the window:

vmware_expanddisk2

Click “OK” to execute the changes on the VM.

USE THE NEWLY ADDED space TO EXTEND AN EXISTING VOLUME GROUP

After enlarging the disk with VMWare, the changes aren’t immediatelly seen on the system:

[jensd@cen ~]$ sudo fdisk -l /dev/sda

Disk /dev/sda: 5368 MB, 5368709120 bytes, 10485760 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk label type: dos
Disk identifier: 0x0009af09

   Device Boot      Start         End      Blocks   Id  System
/dev/sda1   *        2048      206847      102400   83  Linux
/dev/sda2          206848    10485759     5139456   8e  Linux LVM
[jensd@cen ~]$ lsblk
NAME               MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
fd0                  2:0    1    4K  0 disk
sda                  8:0    0    5G  0 disk
├─sda1               8:1    0  100M  0 part /boot
└─sda2               8:2    0  4.9G  0 part
  ├─vg_sys-lv_swap 253:0    0  512M  0 lvm  [SWAP]
  ├─vg_sys-lv_root 253:1    0    2G  0 lvm  /
  ├─vg_sys-lv_var  253:2    0  1.4G  0 lvm  /var
  ├─vg_sys-lv_home 253:3    0  2.5G  0 lvm  /home
  └─vg_sys-lv_tmp  253:4    0  3.5G  0 lvm  /tmp
sdb                  8:16   0    5G  0 disk
└─sdb1               8:17   0    5G  0 part
  ├─vg_sys-lv_home 253:3    0  2.5G  0 lvm  /home
  └─vg_sys-lv_tmp  253:4    0  3.5G  0 lvm  /tmp
sr0                 11:0    1  570M  0 rom

To refresh the devices, we need to ask the virtual SCSI adapter to rescan and update it’s connected devices:

[root@cen jensd]# ls /sys/class/scsi_device/ | while read scsidev ; do echo 1 > /sys/class/scsi_device/$scsidev/device/rescan ; done
[root@cen jensd]# fdisk -l /dev/sda

Disk /dev/sda: 10.7 GB, 10737418240 bytes, 20971520 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk label type: dos
Disk identifier: 0x0009af09

   Device Boot      Start         End      Blocks   Id  System
/dev/sda1   *        2048      206847      102400   83  Linux
/dev/sda2          206848    10485759     5139456   8e  Linux LVM
[root@cen jensd]# lsblk
NAME               MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
fd0                  2:0    1    4K  0 disk
sda                  8:0    0   10G  0 disk
├─sda1               8:1    0  100M  0 part /boot
└─sda2               8:2    0  4.9G  0 part
  ├─vg_sys-lv_swap 253:0    0  512M  0 lvm  [SWAP]
  ├─vg_sys-lv_root 253:1    0    2G  0 lvm  /
  ├─vg_sys-lv_var  253:2    0  1.4G  0 lvm  /var
  ├─vg_sys-lv_home 253:3    0  2.5G  0 lvm  /home
  └─vg_sys-lv_tmp  253:4    0  3.5G  0 lvm  /tmp
sdb                  8:16   0    5G  0 disk
└─sdb1               8:17   0    5G  0 part
  ├─vg_sys-lv_home 253:3    0  2.5G  0 lvm  /home
  └─vg_sys-lv_tmp  253:4    0  3.5G  0 lvm  /tmp
sr0                 11:0    1  570M  0 rom

As you see above, the disk is now seen as a 10GB disk, which is what we want.

Next step in the process is to start using the space that was added to the existing virtual disk /dev/sda. This is very similar as with option 1, we start by creating a new partition that uses the new space:

[jensd@cen ~]$ sudo fdisk /dev/sda
Welcome to fdisk (util-linux 2.23.2).

Changes will remain in memory only, until you decide to write them.
Be careful before using the write command.


Command (m for help): n
Partition type:
   p   primary (2 primary, 0 extended, 2 free)
   e   extended
Select (default p): p
Partition number (3,4, default 3):
First sector (10485760-20971519, default 10485760):
Using default value 10485760
Last sector, +sectors or +size{K,M,G} (10485760-20971519, default 20971519):
Using default value 20971519
Partition 3 of type Linux and of size 5 GiB is set

Command (m for help): t
Partition number (1-3, default 3): 8e
Partition number (1-3, default 3):
Hex code (type L to list all codes): 8e
Changed type of partition 'Linux' to 'Linux LVM'

Command (m for help): p

Disk /dev/sda: 10.7 GB, 10737418240 bytes, 20971520 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk label type: dos
Disk identifier: 0x0009af09

   Device Boot      Start         End      Blocks   Id  System
/dev/sda1   *        2048      206847      102400   83  Linux
/dev/sda2          206848    10485759     5139456   8e  Linux LVM
/dev/sda3        10485760    20971519     5242880   8e  Linux LVM

Command (m for help): w
The partition table has been altered!

Calling ioctl() to re-read partition table.

WARNING: Re-reading the partition table failed with error 16: Device or resource busy.
The kernel still uses the old table. The new table will be used at
the next reboot or after you run partprobe(8) or kpartx(8)
Syncing disks.
[jensd@cen ~]$ lsblk
NAME               MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
fd0                  2:0    1    4K  0 disk
sda                  8:0    0   10G  0 disk
├─sda1               8:1    0  100M  0 part /boot
└─sda2               8:2    0  4.9G  0 part
  ├─vg_sys-lv_swap 253:0    0  512M  0 lvm  [SWAP]
  ├─vg_sys-lv_root 253:1    0    2G  0 lvm  /
  ├─vg_sys-lv_var  253:2    0  1.4G  0 lvm  /var
  ├─vg_sys-lv_home 253:3    0  2.5G  0 lvm  /home
  └─vg_sys-lv_tmp  253:4    0  3.5G  0 lvm  /tmp
sdb                  8:16   0    5G  0 disk
└─sdb1               8:17   0    5G  0 part
  ├─vg_sys-lv_home 253:3    0  2.5G  0 lvm  /home
  └─vg_sys-lv_tmp  253:4    0  3.5G  0 lvm  /tmp
sr0                 11:0    1  570M  0 rom

After writing the new partition table, containing the new partition /dev/sda3, we see that it isn’t added to the system since the disk is busy.

Fortunatelly, partx can override this limitation and update the partition table on a disk that is in use. You need to execute the command twice for it to work as expected:

[jensd@cen ~]$ sudo partx -a /dev/sda
partx: /dev/sda: error adding partitions 1-2
[jensd@cen ~]$ sudo partx -a /dev/sda
partx: /dev/sda: error adding partitions 1-3
[jensd@cen ~]$ lsblk
NAME               MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
fd0                  2:0    1    4K  0 disk
sda                  8:0    0   10G  0 disk
├─sda1               8:1    0  100M  0 part /boot
├─sda2               8:2    0  4.9G  0 part
│ ├─vg_sys-lv_swap 253:0    0  512M  0 lvm  [SWAP]
│ ├─vg_sys-lv_root 253:1    0    2G  0 lvm  /
│ ├─vg_sys-lv_var  253:2    0  1.4G  0 lvm  /var
│ ├─vg_sys-lv_home 253:3    0  2.5G  0 lvm  /home
│ └─vg_sys-lv_tmp  253:4    0  3.5G  0 lvm  /tmp
└─sda3               8:3    0    5G  0 part
sdb                  8:16   0    5G  0 disk
└─sdb1               8:17   0    5G  0 part
  ├─vg_sys-lv_home 253:3    0  2.5G  0 lvm  /home
  └─vg_sys-lv_tmp  253:4    0  3.5G  0 lvm  /tmp
sr0                 11:0    1  570M  0 rom

As you can see, now our system sees /dev/sda3 and we can start using the device to expand our volume group and grow our logical volume with problems:

[jensd@cen ~]$ sudo pvcreate /dev/sda3
  Physical volume "/dev/sda3" successfully created
[jensd@cen ~]$ sudo vgextend vg_sys /dev/sda3
  Volume group "vg_sys" successfully extended
[jensd@cen ~]$ sudo lvextend -L+2G /dev/vg_sys/lv_home
  Extending logical volume lv_home to 4.50 GiB
  Logical volume lv_home successfully resized
[jensd@cen ~]$ sudo xfs_growfs /dev/vg_sys/lv_home
meta-data=/dev/mapper/vg_sys-lv_home isize=256    agcount=20, agsize=32768 blks
         =                       sectsz=512   attr=2, projid32bit=1
         =                       crc=0
data     =                       bsize=4096   blocks=655360, imaxpct=25
         =                       sunit=0      swidth=0 blks
naming   =version 2              bsize=4096   ascii-ci=0 ftype=0
log      =internal               bsize=4096   blocks=853, version=2
         =                       sectsz=512   sunit=0 blks, lazy-count=1
realtime =none                   extsz=4096   blocks=0, rtextents=0
data blocks changed from 655360 to 1179648
[jensd@cen ~]$ df -h /home/
Filesystem                  Size  Used Avail Use% Mounted on
/dev/mapper/vg_sys-lv_home  4.5G  2.5G  2.0G  56% /home

Limits of growing devices

Enlarging a device and creating a new partition is limited if you’re using the MBR partition scheme since this limits every disk to 4 primary partitions. To overcome this limitation, you can use a GPT partition layout or, if not possible, create an extended partition as the last of four possible partitions. In the extended partition we can have a virtual unlimited number of logical partitions.

A more clean solution is to extend existing partitions, which can be done with parted enlarge but this could possible bring down an online files ystem so I wouldn’t advise it for very critical file systems.

Using one of the above methods could possible save you from downtime so use it wisely :)

3 thoughts on “Expand or grow a file system on a Linux VMWare VM without downtime

  1. Don’t parse ‘ls’ output.
    All manner of things can go wrong with that and it’s not even the easiest way to do this.
    Instead, use this:
    https://gist.github.com/TomyLobo/415c95a8f616870109e8cb80204d390f

    Btw, your blog software broke the greater-than sign in that particular line as well, which is why I put the fixed code in a Gist, rather than directly into the comment :)

    More info on why you shouldn’t parse ls output can be found here:
    https://mywiki.wooledge.org/ParsingLs

Leave a Reply

Your email address will not be published. Required fields are marked *