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.
seq
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
Perl
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*
awk
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