I've been learning to program with a really cool introductory book to C and I write off every example and task so I can learn the syntax by heart. I did every file manually until now, but the clicking, naming and saving gets exhausting.

I need a way to create multiple files like bspl0001.c, bspl0002.c, bspl0003.c, etc. and saving them in directory "learning_c" or something.

I'm a noob with Ubuntu / Linux and honestly only run it via VirtualBox because the IDE Geany was easy to set up. Thus, I don't really know how the Terminal works.

edit I've just found myself in this old account of mine and am shaking my head about why I would ever want to learn a code syntax by heart. Funnily enough, I am almost done with my CS / Math BSc studies. Thanks much for the help in hindsight!

  • 1
    Why create all files at once? What I am actually using: press a key combination to 1. see in my code directory what should be the "next" file, 2. create the correctly named file (including shebang) and 3. open it in my editor (in my case Idle). All in one keypress. That way you prevent a lot of (still) unused files. Apr 5, 2015 at 12:27

5 Answers 5


You can do this with these commands:

mkdir learning_c
cd learning_c
touch bspl{0001..0003}.c


  • mkdir learning_c

    • This will create a folder called learning_c in the current folder
    • The current folder usually is your home folder also called ~
    • You can change the current directory using the cd command (i.e. cd Desktop)
  • cd learning_c

    • Yes, you can guess it, you're entering on the newly created folder
  • touch bspl{0001..0003}.c

    • touch is a tool to create empty files and modify timestamps; we're creating empty files.
    • touch myfile will create an empty file called myfile.
    • The ugly code that follows (bspl{0001..0003}.c) is called a brace expansion. This is a great feature of the bash shell that allows you to create long lists of arbitrary string combinations. You can learn more about this in the Bash Hackers Wiki. In this case you will be making a long list of parameters that will be passed to touch. You can also use its long equivalent:

      touch bspl0001.c bspl0002.c bspl0003.c
    • You can change the number of files: if you want 12 files, you can run bspl{0001..0012}.c.

    • The leading zeros (0012 instead of 12) make sure that the output uses zero-padded 4 digits.
  • 4
    Alternately, to save some keystrokes, touch bspl000{1..3}.c
    – Reid
    Apr 5, 2015 at 20:19
  • 1
    @Reid: And what happens if Herios wants 10 or more files?
    – 0x2b3bfa0
    Apr 6, 2015 at 8:30
  • 3
    For those that want to crate a list of files with the same extension touch {test,tes2,tes3}.js
    – Rick
    Sep 22, 2015 at 15:40
  • 1
    @Rick: Isn't what I answer? ;-). Your code can be simplified: touch tes{t,2,3}.js
    – 0x2b3bfa0
    Sep 23, 2015 at 12:29
  • 1
    and you can also do it in one command line: $ mkdir learning_c ;cd learning_c ;touch bspl000{1,2,3,4}.c . The ";" will help you add commands that will execute in order one after the other. Feb 6, 2017 at 6:24

You can use the following python code, you can modify it to fit your needs.
Save the following code with filename filecreator.py

#!/usr/bin/env python
import os
import subprocess
work_path = os.path.abspath(os.path.dirname(__file__))
if not os.path.exists("learning_c"):
n = 10 #put the number as you wish
for i in range(n):
    subprocess.call(['touch', "bsdl"+str(i).zfill(4)+".c"])

And then execute it with this command:

python filecreator.py

Create correctly numbered (next) file with a shortcut key combination

Why create all files at once? The disadvantage is that you will have a lot of empty and unused files. What I am actually using: press a key combination to:

  1. have a script see in my code directory what should be the "next" file,
  2. create the correctly named file (including shebang) and
  3. open the new file in my editor (in my case Idle).

All in one keypress. That way you prevent a lot of (still) unused files; The files are only created if you need them.

A simplified version below (not running step 3). On every keypress, it will create a correctly numbered file like:

bspl0001.c, bspl0002.c, bspl0003.c etc
#!/usr/bin/env python3
import os
#--- set your code directory below
dr = "/path/to/your/coding_files"
#--- set the desired (base) name extension and shebang below (leave it ""if you don't want an automatically set shebang)
name_initial = "bspl"
extension = ".c"
shebang = ""

existing = os.listdir(dr)
n = 1
while True:
    file = dr+"/"+name_initial+str(n).zfill(4)+extension
    if os.path.exists(file):
        n = n+1
        with open(file, "wt") as out:

How to use

  1. Copy the script into an empty file
  2. In the head section, set the path to your directory (and optional: change the base name and/or extension, shebang).
  3. Save the script as create_empty.py
  4. Run the script from a shortcut: System Settings > Keyboard > Custom Shortcuts. Add the command:

    python3 /path/to/create_empty.py

The bash way is good, but what if you are working with a shell that doesn't support the curly brace expansion ? touch file{1..10} doesn't work for me on mksh for instance. Here's three alternative ways that work regardless of the shell.


A more shell-neutral approach would be to combine seq command to generate sequence of numbers formatted with printf options , and pass it to xargs command. For example,

$ ls -l
total 0
$ seq -f "%04.0f" 10 | xargs -I "{}" touch bspl"{}".c                 
$ ls
bspl0002.c  bspl0004.c  bspl0006.c  bspl0008.c  bspl0010.c
bspl0001.c  bspl0003.c  bspl0005.c  bspl0007.c  bspl0009.c


Of course, Perl , being quite a widespred *nix tool, can do that as well. The specific one-liner command that we have here is the following:

perl -le 'do { $var=sprintf("%s%04d.c",$ARGV[0],$_ ); open(my $fh, ">", $var);close($fh) } for $ARGV[1] .. $ARGV[2]' bslp 1 5 

Effectively what happens here is that we specify 3 command-line arguments: filename prefix, starting index, and ending index. Then we use do { } for $ARGV[1] .. $ARGV[2] to iterate for a specific range of numbers. Say, $ARGV[1] was 5 and $ARGV[2] was 9, we would iterate over 5,6,7,8 and 9.

What happens on each iteration within the curly braces ? we take each number specified with $_, and using sprintf() function create a string m which splices up the prefix (first command-line argument, $ARGV[0]) and the given number, but filling up the number with 4 zeros (which is done by printf-style of formatting , %04d part), and attach the .c suffix.As a result on each iteration we make up a name like bspl0001.c.

The open(my $fh, ">", $var);close($fh) effectively acts as touch command, creating a file with specified name.

While slightly lengthy it performs quite well, in fashion similar to Jacob Vlijm's python script. It can also be converted to a script for readability if desired, like so:

#!/usr/bin/env perl
use strict;
use warnings;

for my $i ( $ARGV[1] .. $ARGV[2] ) { 
    my $var=sprintf("%s%04d.c",$ARGV[0],$i ); 
    open(my $fh, ">", $var) or die "Couldn't open " . $var ;
    close($fh) or die "Couldn't close " . $var ;

Lets test this. First the one-liner:

$ ls -l
total 0
$ perl -le 'do { $var=sprintf("%s%04d.c",$ARGV[0],$_ ); open(my $fh, ">", $var);close($fh) } for $ARGV[1] .. $ARGV[2]' bslp 1 5
$ ls -l                                                                                               
total 0
-rw-rw-r-- 1 xieerqi xieerqi 0 2月   5 23:36 bslp0001.c
-rw-rw-r-- 1 xieerqi xieerqi 0 2月   5 23:36 bslp0002.c
-rw-rw-r-- 1 xieerqi xieerqi 0 2月   5 23:36 bslp0003.c
-rw-rw-r-- 1 xieerqi xieerqi 0 2月   5 23:36 bslp0004.c
-rw-rw-r-- 1 xieerqi xieerqi 0 2月   5 23:36 bslp0005.c

And now the script:

$ ls -l
total 4
-rwxrwxr-x 1 xieerqi xieerqi 244 2月   5 23:57 touch_range.pl*
$ ./touch_range.pl bspl 1 5                                                                           
$ ls -l
total 4
-rw-rw-r-- 1 xieerqi xieerqi   0 2月   5 23:58 bspl0001.c
-rw-rw-r-- 1 xieerqi xieerqi   0 2月   5 23:58 bspl0002.c
-rw-rw-r-- 1 xieerqi xieerqi   0 2月   5 23:58 bspl0003.c
-rw-rw-r-- 1 xieerqi xieerqi   0 2月   5 23:58 bspl0004.c
-rw-rw-r-- 1 xieerqi xieerqi   0 2月   5 23:58 bspl0005.c
-rwxrwxr-x 1 xieerqi xieerqi 244 2月   5 23:57 touch_range.pl*


Another approach would be with awk, running a for loop, redirecting to a specific file. The approach is similar to the perl one-liner with command-line arguments. While awk is primarily a text processing utility, it still can do some cool system programming.

$ awk 'BEGIN{for(i=ARGV[2];i<=ARGV[3];i++){fd=sprintf("%s%04d.c",ARGV[1],i); printf "" > fd;close(fd)}}' bslp 1 5
  • I wrote a variation to write 1K random junk for testing performance overhead of antimalware/security software seq -f "%04.0f" 100 | xargs -I "{}" dd if=/dev/random of=random-"{}.bin" bs=1K count=1 status=none
    – Andrew
    Dec 1, 2022 at 20:37

Just stumbled onto this page looking for something else...in case anyone else needs to do this, I think it is easiest using touch and a for loop.

for i in {1..10}; do touch file$i.txt; done

Which will create file1.txt up to file10.txt in the working directory. Of course you can specify a directory too such as

for i in {60..69}; do touch ./texts/file$i.txt; done

Which will create file60.txt up to file69.txt in the directory ./texts


You must log in to answer this question.

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