[ruby-core:119901] [Ruby master Bug#20891] Dir.foreach does not give a static list.

Issue #20891 has been reported by karasu (karasu k). ---------------------------------------- Bug #20891: Dir.foreach does not give a static list. https://bugs.ruby-lang.org/issues/20891 * Author: karasu (karasu k) * Status: Open * ruby -v: 2.7.0 * Backport: 3.1: UNKNOWN, 3.2: UNKNOWN, 3.3: UNKNOWN ---------------------------------------- I was using `Dir.foreach` with a block to batch change filenames. The sample code is something like this: ```rb look_up_table = File.open('look-up-table' ,'w') Dir.foreach('.').each_with_index do |file, index| File.rename(file, index) look_up_table << "#{file}: #{index}\n" end ``` As first I thought it's good, but I found that some indices might be missing. After staring at the look-up table for hours, I realised some files were modified more than once, and this is strange for me. It means that in each iteration of `Dir.foreach`, it acutally **might** fetch the files to see if there are new files that are not in the list before? What I mean **might** is that this situation does not occur anytime, I don't know how to or not to trigger it, but this is what I faced. I am aware that in `Dir.foreach` it might have some `yield` so this behavior might be normal for you guys, but since the function is called `foreach`, I assumed that it should give a list that is not gonna change once it's established. My later fix change to the sample code is: ```rb look_up_table = File.open('look-up-table' ,'w') Dir.foreach('.').to_a.each_with_index do |file, index| File.rename(file, index) look_up_table << "#{file}: #{index}\n" end ``` You can see that I add a `to_a` to change the result from `Dir.foreach` into an array, and rename those files according to it, instead of the result itself. I wonder if this is an old issue but I cannot find it anywhere else. Thanks in advance. Both English and Japanese are welcome! (I know that `Dir.foreach` will give `.` and `..` as well, but let's just forget it for now.) -- https://bugs.ruby-lang.org/

Issue #20891 has been updated by shyouhei (Shyouhei Urabe). ```ruby a = [ 1, 2, 3 ] a.each do |i| a << i end ``` You are doing this using your file system. The container (directory) itself is modified during it is experiencing iteration, means whatever unexpected things can occur. The reason why you sometimes see the breakage and sometimes not is because a filesystem directory is a much much complicated construct than a mere array. ---------------------------------------- Bug #20891: Dir.foreach does not give a static list. https://bugs.ruby-lang.org/issues/20891#change-110618 * Author: karasu (karasu k) * Status: Open * ruby -v: 2.7.0 * Backport: 3.1: UNKNOWN, 3.2: UNKNOWN, 3.3: UNKNOWN ---------------------------------------- I was using `Dir.foreach` with a block to batch change filenames. The sample code is something like this: ```rb look_up_table = File.open('look-up-table' ,'w') Dir.foreach('.').each_with_index do |file, index| File.rename(file, index) look_up_table << "#{file}: #{index}\n" end ``` As first I thought it's good, but I found that some indices might be missing. After staring at the look-up table for hours, I realised some files were modified more than once, and this is strange for me. It means that in each iteration of `Dir.foreach`, it acutally **might** fetch the files to see if there are new files that are not in the list before? What I mean **might** is that this situation does not occur anytime, I don't know how to or not to trigger it, but this is what I faced. I am aware that in `Dir.foreach` it might have some `yield` so this behavior might be normal for you guys, but since the function is called `foreach`, I assumed that it should give a list that is not gonna change once it's established. My later fix change to the sample code is: ```rb look_up_table = File.open('look-up-table' ,'w') Dir.foreach('.').to_a.each_with_index do |file, index| File.rename(file, index) look_up_table << "#{file}: #{index}\n" end ``` You can see that I add a `to_a` to change the result from `Dir.foreach` into an array, and rename those files according to it, instead of the result itself. I wonder if this is an old issue but I cannot find it anywhere else. Thanks in advance. Both English and Japanese are welcome! (I know that `Dir.foreach` will give `.` and `..` as well, but let's just forget it for now.) -- https://bugs.ruby-lang.org/
participants (2)
-
karasu (karasu k)
-
shyouhei (Shyouhei Urabe)