Creating files with Python and mimicking the "touch command"
Tags: python, linux, 100daysofcode, codenewbie
Published: 2020-08-16 15:34:00

# We will learn the following while working on our Python Script:

1. [Creating files with Python](#creating-files)
  + [Creating a single file](#creating-single-file)
  + [Creating multiple files](#creating-multiple-files)
  + [Providing filenames from the command line](#command-line)
  + [Testing our script](#test)

2. [Touch command](#touch)
  + [Getting the access time and modified time of a file](#stat)
  + [Getting the current time](#ctime)
  + [Updating Access and Modified time in a file](#utime)
  + [Implementing the Touch Command](#implement)

3. [Result](#result)

## <a name="creating-files">Creating files with Python</a>

### <a name="creating-single-file">Creating a single file</a>

Here's a one-liner for creating a file with Python.

```python
open('hello_world.txt','w')
```

This single statement creates `hello_world.txt`, but we don't want fixed file names, do we?

The question is, how to conveniently provide input to the script to create a file with Python.

We can use a variable for storing the name of the file, like this...

```python
filename = "hello_world.txt"
open(filename, 'w')
```

But this will be a mess if we want to create multiple files with Python, as each time we want to create a file, we would need to update `filename` variable manually which ain't so cool.

### <a name="creating-multiple-files">Creating multiple files</a>

The solution to the above problem is, making a list of filenames.

```python
filenames = ['hello_world.txt', 'random_file.txt', 'lol.txt']
for filename in filenames:
    open(filename, 'w')
```

This is MUCH BETTER 🤩! But wait, It's only good for one-time use 😕. What if we want to make more files later in a single go?

Then we would have to update the `filenames` list again and again. 😑

### <a name='command-line'>Providing filenames from the command line</a>

For this fix, we can provide values (filenames) from the command line! 😃 We only need to make two changes in our existing code.

Add `from sys import argv` and use the value of `argv` with for `filenames`.

```python
from sys import argv

filenames = argv[1:] # Ignore the first element (script file)

for filename in filenames:
    open(filename, 'w')
```

This seems to work just fine but there's a nasty bug in it.

If the file already exists, it will wipe the whole file's contents. Thanks to the file access mode `'w'` (write mode) which we used.

The fix is very simple. We just need to replace `'w'` with `'a'` (append mode) which will ignore the files which already exist and create new ones if they don't.

```python
from sys import argv

filenames = argv[1:] # Ignore the first element (script file)

for filename in filenames:
    open(filename, 'a') # Using append mode now
```

## <a name='test'>Testing our script</a>

I saved the script as `touch.py` here's the execution...

![creating files in terminal](https://dev-to-uploads.s3.amazonaws.com/i/srium4ced05mamyl93ca.png)
<figcaption>Creating multiple files with our Python script</figcaption>

![checking if file remains intact](https://dev-to-uploads.s3.amazonaws.com/i/yhjencd4d02ok2ex5pcg.png)
<figcaption>Existing files remain unchanged, YAY!</figcaption>

## <a name = "touch" >Touch command</a>

Our script is GOOOOOODDD!!! 🔥🔥🔥

But there's still one thing we can add to make it behave more like touch command, that is, updating a file's access and modified time.

For the sake of keeping things simple, we will just update the modified time of the file.

### <a name='stat'>Getting the access time and modified time of a file</a>

The `os` module in Python has a `stat` function that performs a stat system call (runs a stat command behind the scenes) and returns the result in an accessible way.

```python
from os import stat
st_info = stat(filename)

access_time = st_info.st_atime 
modified_time = st_info.st_mtime
```
We can use the result `st_info` which contains the status of the file including the access and modified time for modifying the file.

### <a name='ctime'>Getting the current time</a>

`time` function in the `time` module returns the current time which we can directly use in our script for modifying the files with our script.

```python
from time import time
current_time = time() # current time in seconds (since Epoch)
```

### <a name='utime'>Updating Access and Modified time in a file</a>

The `os` module also has a function for updating this access and modified time called `utime`.

Here's how this can be done,

```python
from os import utime

# if the second argument isn't passed, it will set the access
# and modified time to current time

utime(filename)

# for setting our custom access and modified time
utime(filename, (access_time, current_time))
```

### <a name='implement'>Implementing the Touch Command</a>

Now, we can finally put together everything we have done so far in one final script.

```python

from sys import argv
from time import time
from os import utime, stat


for name in argv[1:]:
  open(name, 'a')
  st_info = stat(name) # Storing file status
  # setting access time with file's access time (no change)
  # setting modified time with current time of the system)
  utime(name, (st_info.st_atime, time()))
```
## <a name='result'>Result</a>

Finally, It's time we use the script for creating files and stuff.

![Creating multiple files](https://dev-to-uploads.s3.amazonaws.com/i/nhly2jsv5vx0vorzos0g.png)
<figcaption>Multiple files created Succesfully! 🔥</figcaption>

![giving existing file to our script](https://dev-to-uploads.s3.amazonaws.com/i/uu5l4odtwrs4jbv8c13z.png)
<figcaption>Our script successfully updates the modified time of existing file!! 🔥</figcaption>

#### That's it! Our script makes multiple files and mimics the touch command as it sets the modified time! 🎉🎉🎉

You can tweak it and add more features to make it a complete touch command clone.

[Link to script file](https://github.com/gagangulyani/touch-command-python)