Объяснение , почему Вы получаете ту ошибку: PCRE использует свободное определение Perl того, каков разделитель. Ваши внешние []
с похожи на допустимые разделители к нему, заставляя его читать [:punct:]
как regex часть.
(О, и избегают ereg
функции, если Вы можете - они не собираются быть включенными в PHP 5.3.)
Я полагаю, вы ищете существующий метод GetFileSystemInfos (string, SearchOptions). Если вы укажете AllDirectories в качестве значения SearchOptions, он будет рекурсивно искать переданные в папке.
Например:
public static List<FileSystemInfo> GetAllFilesAndDirectories ( string dir ) {
DirectoryInfo info = new DirectoryInfo(dir);
FileSystemInfo[] all = info.GetFileSystemInfos("*", SearchOptions.AllDirectories);
return new List<FileSystemInfo>(all);
}
Если вы хотите написать долгий путь, вы можете сделать следующее
public static List<FileSystemInfo> GetAllFilesAndDirectories ( string dir ) {
int i = 0;
List<DirectoryInfo> toProcess = new List<DirectoryInfo>();
List<FileSystemInfo> list = new List<FileSystemInfo>();
toProcess.Add(new DirectoryInfo(dir));
while ( i < toProcess.Count ) {
DirectoryInfo curDir = toProcess[i];
foreach ( FileSystemInfo curFile in curDir.GetFileSystemInfos() ) {
list.Add(curFile);
DirectoryInfo maybe = curFile as DirectoryInfo;
if ( maybe != null ) {
toProcess.Add(maybe);
}
i++;
}
return list;
}
FileSystemInfo[] all = info.GetFileSystemInfos("*", SearchOptions.AllDirectories);
return new List<FileSystemInfo>(all);
}
Если вы хотите "удобный для новичков метод", я могу предложить метод bobbymcr .
Но, если вы хотите сохранить структуру кода, я воспроизведу ниже код, который я разместил в , ваш следующий вопрос :
static IEnumerable<FileSystemInfo> GetAllFilesAndDirectories(string path)
{
string currentDirectory = "";
string[] files = Directory.GetFiles( // skip empty subfolders
path, "*.*", SearchOption.AllDirectories);
foreach (string file in files)
{
if(currentDirectory != Path.GetDirectoryName(file))
{
// First time in this directory: return it
currentDirectory = Path.GetDirectoryName(file);
yield return new DirectoryInfo(currentDirectory);
}
yield return new FileInfo(file);
}
}
Я думаю, что с точки зрения читабельности кода лучше всего написать рекурсивную функцию. Рекурсивная функция - это функция, которая вызывает себя до тех пор, пока не достигнет точки, в которой не нужно вызывать какую-либо другую функцию.
Для иллюстрации факториал n, записанный как n! и определяемая как величина 1 x 2 x 3 x ... xn (где n - положительное целое число) может быть довольно легко определена рекурсивным способом следующим образом.
public int factorial(int n)
{
if (n < 0)
{
throw new Exception("A factorial cannot be calculated for negative integers.");
}
if (n == 0 || n == 1)
{
// end condition, where we do not need to make a recursive call anymore
return 1;
}
else
{
// recursive call
return n * factorial(n - 1);
}
}
NB: 0! и 1! определены равными 1.
Аналогичным образом, метод для перечисления всех файлов и папок по заданному пути также может быть определен рекурсивно. Это потому, что файлы и папки имеют рекурсивную структуру.
Следовательно, будет работать следующий метод:
public static List<FileSystemInfo> GetAllFilesAndFolders(string folder)
{
// NOTE : We are performing some basic sanity checking
// on the method's formal parameters here
if (string.IsNullOrEmpty(folder))
{
throw new ArgumentException("An empty string is not a valid path.", "folder");
}
if (!Directory.Exists(folder))
{
throw new ArgumentException("The string must be an existing path.", "folder");
}
List<FileSystemInfo> fileSystemInfos = new List<FileSystemInfo>();
try
{
foreach (string filePath in Directory.GetFiles(folder, "*.*"))
{
// NOTE : We will add a FileSystemInfo object for each file found
fileSystemInfos.Add(new FileInfo(filePath));
}
}
catch
{
// NOTE : We are swallowing all exceptions here
// Ideally they should be surfaced, and at least logged somewhere
// Most of these will be security/permissions related, i.e.,
// the Directory.GetFiles method will throw an exception if it
// does not have security privileges to enumerate files in a folder.
}
try
{
foreach (string folderPath in Directory.GetDirectories(folder, "*"))
{
// NOTE : We will add a FileSystemInfo object for each directory found
fileSystemInfos.Add(new DirectoryInfo(folderPath));
// NOTE : We will also add all FileSystemInfo objects found under
// each directory we find
fileSystemInfos.AddRange(GetAllFilesAndFolders(folderPath));
}
}
catch
{
// NOTE : We are swallowing all exceptions here
// Ideally they should be surfaced, and at least logged somewhere
// Most of these will be security/permissions related, i.e.,
// the Directory.GetDirectories method will throw an exception if it
// does not have security privileges to enumerate files in a folder.
}
return fileSystemInfos;
}
Следует отметить, что этот метод будет "ходить" вся структура каталогов под папкой и НЕ вернется, пока она не "пройдется" по всей иерархии. Следовательно, возврат может занять много времени, если нужно найти много объектов.
Также следует отметить, что читаемость этого метода может быть дополнительно улучшена с помощью лямбда-выражений и методов расширения.
NB : Проблема с использованием Directory.GetFiles и Directory.GetDirectories для рекурсии подпапок заключается в том, что при возникновении каких-либо исключений (например, связанных с разрешениями безопасности) метод ничего не возвращает, тогда как рекурсивное выполнение вручную позволяет обрабатывать эти исключения и все же получить набор файлов обратно.
Вот самый короткий способ, который я могу придумать:
static List<FileSystemInfo> GetAllFilesAndDirectories(string dir)
{
DirectoryInfo dirInfo = new DirectoryInfo(dir);
List<FileSystemInfo> allFilesAndDirectories = new List<FileSystemInfo>();
allFilesAndDirectories.AddRange(dirInfo.GetFiles("*", SearchOption.AllDirectories));
allFilesAndDirectories.AddRange(dirInfo.GetDirectories("*", SearchOption.AllDirectories));
return allFilesAndDirectories;
}
Он вернет список всех файлов и каталогов на всех уровнях, начиная с заданного пути. Они будут возвращены в следующем порядке: все файлы, а затем все каталоги.
Вы специально просили "сделать это глупее". Я думаю, что два других ответа очень хороши, но вот еще один способ сделать это с еще более простым, легко понятным кодом начального уровня.
http://support.microsoft.com/kb/303974
Править
Я знаю, что это не 3.0, но это все еще испытанный, проверенный и простой для понимания способ сделать это.
public List<Object> GetFilesAndDirectories(string path)
{
List<Object> lst = new List<Object>();
string[] dirs = null;
try
{
dirs = Directory.GetDirectories(path);
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
foreach (string d in dirs)
{
string[] files = null;
try
{
files = Directory.GetFiles(d);
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
foreach (string f in files)
{
lst.Add(f);
}
lst.Add(d);
lst.AddRange(GetFilesAndDirectories(d));
}
return lst;
}
List<Object> stuff = GetFilesAndDirectories(someRoot);