tags:

views:

62

answers:

3

i want to create a new file in a folder with existing files with names in a numerical order eg. 1, 2, 3, 4...

i want to check what is the last nr and then create a file with one nr over that one.

i know i should use file_exists but i don't know exactly how to use it, in a for loop maybe? but how?

would be nice if someone could give me a hint

+5  A: 

I think this is your best bet (see revisions for previous versions):

$files    = glob('/path/to/dir/*');      // get all files in folder
natsort($files);                         // sort
$lastFile = pathinfo(array_pop($files)); // split $lastFile into parts
$newFile  = $lastFile['filename'] +1;    // increase filename by 1

if(file_exists("/path/to/dir/$newFile")) { // do not write file if it exists
    die("$newFile aready exists");
}
file_put_contents("/path/to/dir/$newFile", 'stuff');  // write new file    

As long as your filenames in the folder start with numbers, this should always write the highest numbered filename incremented by one, e.g.

1,5,10                  => writes file 11
1.txt, 5.gif, 10.jpg    => writes file 11
1, 5.txt, 10_apple.txt  => writes file 11

If there is a file not starting with a number, the above approach won't work, because numbers are sorted before characters and thus nothing would be written for e.g.

1,5,10,foo => foo+1 equals 1, already exists, nothing written

You can get around this by changing the pattern for glob to /path/[0-9]*, which would then only match files starting with a number. That should be pretty solid then.

Note natsort behaves different on different OS. The above works fine on my Windows machine, but you will want to check the resulting sort order to get it working for your specific machine.

See the manual for further info on how to use glob(), natsort() and pathinfo();

Gordon
so 1.jpg and 2.gif wont matter or are u assuming they got same extension?
weng
The asterisk in glob matches all files in the folder, regardless of extension.
Gordon
If you removed a file (that was obsolete or something), then this fails, since the number of files is unequal to the latest 'id-number'
Veger
@Gordon: Like the new approach. =)
Alix Axel
@Veger yes, but I noted that in the answer. See the second approach that circumvents this. @Alix thanks :)
Gordon
Much better indeed! :) Better to remove the first approach, since it is 'dangerous' if used wrong...
Veger
i think there is a bug in your code. you have to use krsort after natsort to get it right..
weng
@noname natcase seems to be behave different on different OS, which is kinda dull. The above works fine on Win machines. See the comments below natsort in the manual for a discussion.
Gordon
$gordon..yes you are right. according to the manual you should have this one, but i think they wrote wrong in the manual cause im on Mac and it works without it...thx for correction.
weng
+2  A: 

Maybe like this?

$name = 'filename';
$ext = '.txt';
$i = 1;
$tmpname = $name . $ext;
while(file_exists($tmpname)) {
  $i++;
  $tmpname = $name . $i . $ext;
}

// $tmpname will be a unique filename by now
Emil Vikström
Clean and nice but it should be noted that it will write the first file not in the directory, e.g. when there is 10 files and I delete 1.txt, the above code will create 1.txt on the next run, instead of 11.txt
Gordon
+1  A: 

one way. imagine filenames 1.txt, 2.txt etc

$dir = "/path";
chdir($dir);
$files = glob("[0-9]*.txt");
print "Files aftering globbing: ";
print_r($files);
sort($files,SORT_NUMERIC);
print "After sorting using numeric sort: ";
print_r($files);
# get latest file
$newest=end($files);
$s=explode(".",$newest);
$s[0]=$s[0]+1;
$newname=$s[0].".txt";
touch($newname);

output

$ ls *txt
10.txt  11.txt  1.txt  2.txt  3.txt  4.txt  5.txt  6.txt  7.txt  8.txt  9.txt

$ php test.php
Files aftering globbing: Array
(
    [0] => 1.txt
    [1] => 10.txt
    [2] => 11.txt
    [3] => 2.txt
    [4] => 3.txt
    [5] => 4.txt
    [6] => 5.txt
    [7] => 6.txt
    [8] => 7.txt
    [9] => 8.txt
    [10] => 9.txt
)
After sorting using numeric sort: Array
(
    [0] => 1.txt
    [1] => 2.txt
    [2] => 3.txt
    [3] => 4.txt
    [4] => 5.txt
    [5] => 6.txt
    [6] => 7.txt
    [7] => 8.txt
    [8] => 9.txt
    [9] => 10.txt
    [10] => 11.txt
)

$ ls *.txt
10.txt  11.txt  **12.txt**  1.txt  2.txt  3.txt  4.txt  5.txt  6.txt  7.txt  8.txt  9.txt
ghostdog74
Worst piece of code I've seen all day, **1)** `glob()` needs to know `$dir`, **2)** you need to use {0,1,2,3,4,5,6,7,8,9} and the GLOB_BRACE flag and even that won't match `10.txt` for instance and **3)** `glob()` already sorts stuff, why sort it again?
Alix Axel
You should go try globbing and see. create files 1.txt to 20.txt. Then do the normal glob , and then use sort() by numeric + globbing. You will see the difference.
ghostdog74
Try executing this with a path different from the current directory. On my Windows machine, the sort looks different. It will be descending and not in the right order, probably because I have files 123_foo.txt in the directory as well.
Gordon