从RecursiveDirectoryIterator过滤目录 [英] Filter directorie(s) from RecursiveDirectoryIterator

查看:48
本文介绍了从RecursiveDirectoryIterator过滤目录的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

因此,在学习一本Java编程书的同时,为了寻求更多有关Android开发的知识,我遇到了JSONObject和JSONArray. 经过一番研究,我整理了一个php脚本来读取目标目录的内容,输出是一个JSON文件,其中包含足够的信息来解析我的学习材料所经过的Java类.

So in my quest to learn more about Android Development, while studying a Java Programming book, I came across JSONObject and JSONArray. After a bit of research, I put together a php script to read the contents of a target directory with the output being a JSON file with enough info to parse with a Java class that my study materials go over.

唯一的问题是,我接触php已经有好几年了,我从几个来源收集到的信息是我唯一能理解的-这就是这种情况:

The only issue is, it has been years since I have touched php and the bit that I put together from several sources is the only bit I can understand - so here is the situation:

如何从结果中过滤掉(在将结果添加到JSON文件之前)一系列排除项(文件和/或目录),例如:"@ eaDir","Thumbs.db",.DS_File"等

How can I filter out from my results (before they are added to my JSON file) an array of exclusions (file and/or directory), e.g.: "@eaDir", "Thumbs.db", ".DS_File", etc.

这是有问题的代码:

#!/usr/bin/php
<?php

/* Run with: php [filename].php /path/to/folder/
    Outputs file_list.json in target folder */

// Where are we running on?
if (PHP_SAPI === 'cli') {
    $argument1 = $argv[1];
    $argument2 = $argv[2];
}
else {
    $argument1 = $_GET['argument1'];
    $argument2 = $_GET['argument2'];
}

// Set output dir and file
$out = $argument1 . '/file_list.json';

/*
 * @param Array $types
 * @abstract Array of allowed file types
 */
$types = Array ('mp3', 'ogg');

if (!isset($argv[1]))
    exit("Must specify a directory to scan\n");

if (!is_dir($argv[1]))
    exit($argv[1]."' is not a directory\n");

/*
 * @name getList
 * @param Array $dir
 * @param Array $types
 * @abstract Recursively iterates over specified directory
 *           populating array based on array of file extensions
 * @return Array $files
 */
function getList($dir, $types) {
    $it = new RecursiveDirectoryIterator($dir);
    foreach(new RecursiveIteratorIterator($it) as $file) {
        if (in_array(strtolower(array_pop(explode('.', $file))), $types)) {
            $files[] = $file->__toString();
        } 
    }
    return $files; 
}

/*
 * @name getDetails
 * @param Array $dir
 * @param Array $types
 * @abstract Recursively iterates over specified directory
 *           populating array with details of each file
 * @return Array $files
 */
function getDetails($types, $array)
{
    foreach($types as $type)
    {
        foreach($array as $file)
        {
            if (strcasecmp($type, array_pop(explode('.', $file))) == 0) {
                $files[$type][basename($file)];
                $files[$type][basename($file)]['source'] = $file;
                $files[$type][basename($file)]['size'] = filesize($file);
            }
        }
    }
    return array('files'=>$files);
}

if (!function_exists('json_encode')) {

    /*
     * @name json_encode
     * @param Mixed $val
     * @abstract Alternate emulated json_encode function
     * @return Object $res
     */
    function json_encode($val)
    {
        if (is_string($val)) return '"'.addslashes($val).'"';
        if (is_numeric($val)) return $val;
        if ($val === null) return 'null';
        if ($val === true) return 'true';
        if ($val === false) return 'false';

        $assoc = false;
        $i = 0;
        foreach ($val as $k=>$v){
            if ($k !== $i++){
                $assoc = true;
                break;
            }
        }
        $res = array();
        foreach ($val as $k=>$v){
            $v = json_encode($v);
            if ($assoc){
                $k = '"'.addslashes($k).'"';
                $v = $k.':'.$v;
            }
            $res[] = $v;
        }
        $res = implode(',', $res);
        return ($assoc)? '{'.$res.'}' : '['.$res.']';
    }
}

/* Open file in write mode */
$fp = fopen($out, 'w');

/* Run application & save file */
fwrite($fp, json_encode(getDetails($types, getList($argv[1], $types))));

/* Close file */
fclose($fp);

exit();

我在Synology DS1513 +上运行它,该DS1513 +始终会弹出名称为@eaDir的目录.这是我禁用的索引编制过程,但会在下一次更新时恢复(有时在重新启动后). 我想添加更多文件类型,而不必担心脚本检查上面提到的目录.

I run this on a Synology DS1513+ which is always spitting out directories with the name of @eaDir. This is an indexing process that I disable but comes back on the next update (sometimes after a restart). I would like to add more files types without having to worry about the script checking the directories I mentioned above.

我该怎么做?

经过更多的阅读和研究之后,我添加了一个嵌套的if条件来过滤目录,这是包含以下更改的代码:

After a bit more of reading and research, I added a nested if condition to filter out directories, this is the code with the changes included:

#!/usr/bin/php
<?php

/* Run with: php [filename].php /path/to/folder/
  Outputs file_list.json in target folder */

// Where are we running on?
if (PHP_SAPI === 'cli') {
    $argument1 = $argv[1];
    $argument2 = $argv[2];
} else {
    $argument1 = $_GET['argument1'];
    $argument2 = $_GET['argument2'];
}

// Set output dir and file
$out = $argument1 . '/file_list.json';

/*
 * @param Array $types
 * @abstract Array of allowed file types
 */
$types = ['mp3', 'ogg', 'jpg'];
$ignoreDir = ['@eaDir'];

if (!isset($argv[1])) {
    exit("Must specify a directory to scan\n");
}

if (!is_dir($argv[1])) {
    exit($argv[1] . "' is not a directory\n");
}

/*
 * @name getList
 * @param Array $dir
 * @param Array $types
 * @param Array $ignoreDir
 * @abstract Recursively iterates over specified directory
 *           populating array based on array of file extensions
 *           while ignoring directories specified in ignoreDir
 * @return Array $files
 */

function getList($dir, $types, $ignoreDir) {
    $it = new RecursiveDirectoryIterator($dir);
    foreach (new RecursiveIteratorIterator($it) as $file) {
        if (in_array(strtolower(array_pop(explode('.', $file))), $types)) {
            if (!in_array($it, $ignoreDir)) {
                $files[] = $file->__toString();
            }
        }
    }
    return $files;
}

/*
 * @name getDetails
 * @param Array $dir
 * @param Array $types
 * @abstract Recursively iterates over specified directory
 *           populating array with details of each file
 * @return Array $files
 */

function getDetails($types, $array) {
    foreach ($types as $type) {
        foreach ($array as $file) {
            if (strcasecmp($type, array_pop(explode('.', $file))) == 0) {
                $files[$type][basename($file)]['name'] = basename($file);
                $files[$type][basename($file)]['size'] = filesize($file);
                $files[$type][basename($file)]['source'] = $file;
                $files[$type][basename($file)]['date'] = date ("F d Y H:i:s", filemtime($file));
            }
        }
    }
    return array('files' => $files);
}

if (!function_exists('json_encode')) {

    /*
     * @name json_encode
     * @param Mixed $val
     * @abstract Alternate emulated json_encode function
     * @return Object $res
     */
    function json_encode($val)
    {
        if (is_string($val)) return '"'.addslashes($val).'"';
        if (is_numeric($val)) return $val;
        if ($val === null) return 'null';
        if ($val === true) return 'true';
        if ($val === false) return 'false';

        $assoc = false;
        $i = 0;
        foreach ($val as $k=>$v){
            if ($k !== $i++){
                $assoc = true;
                break;
            }
        }
        $res = array();
        foreach ($val as $k=>$v){
            $v = json_encode($v);
            if ($assoc){
                $k = '"'.addslashes($k).'"';
                $v = $k.':'.$v;
            }
            $res[] = $v;
        }
        $res = implode(',', $res);
        return ($assoc)? '{'.$res.'}' : '['.$res.']';
    }
}

/* Open file in write mode */
$fp = fopen($out, 'w');

/* Run application & save file */
fwrite($fp, json_encode(getDetails($types, getList($argv[1], $types, $ignoreDir)), JSON_PRETTY_PRINT));

/* Close file */
fclose($fp);

exit();

我仍然有兴趣了解有关RecursiveDirectoryIterator如何使用过滤器的更多信息,但是到目前为止,这种方法已经可以满足我的需求.

I am still interested in learning more about how a RecursiveDirectoryIterator can use filters but this is working so far for my needs.

推荐答案

PHP有一个名为 RecursiveCallbackFilterIterator

http://php.net/manual/en/class.recursivecallbackfilteriterator.php

如果使用它代替当前的递归迭代器,则可以在迭代每个文件/目录之前进行预过滤".

If you use this instead of your current recursive iterator it will let you "pre-filter" before you iterate over each file/directory.

您可以根据需要进行过滤,包括目录,文件名,文件大小等.

You can filter by whatever you want including directories, filenames, filesizes etc.

然后您可以排除这样的目录:

You can then exclude directories like this:

$dir = new RecursiveDirectoryIterator('dirYouWantToIterateOver');

//define the directories you don't want to include
$excludeDirs = array('@eaDir', 'notThisDir', 'notInThisOtherDir');

$files = new RecursiveCallbackFilterIterator($dir, function($file, $key, $iterator) use ($excludeDirs){
    if($iterator->hasChildren() && !in_array($file->getFilename(), $excludeDirs)){
        return true;
    }
    return $file->isFile();
});

foreach(new RecursiveIteratorIterator($files) as $file){
  //do something with each file
  echo($file->getPathname() . PHP_EOL);
}

这篇关于从RecursiveDirectoryIterator过滤目录的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆