使用PHP删除FTP存档中具有特定名称的所有目录

时间:2008-11-09 15:45:08

标签: php ftp

如果只能通过FTP访问服务器,那么如何删除目录树中具有特定名称的所有目录?

为了澄清,我想迭代一个目录树并删除名称与某个字符串通过FTP匹配的每个目录。在PHP中实现这一点的方法很好 - 我应该从哪里开始?此外,如果有人知道任何已经执行此操作的实用程序,那也会很棒。

3 个答案:

答案 0 :(得分:4)

这是一个起点 - 一个函数,它将扫描FTP目录并打印树中与模式匹配的任何目录的名称。我已经对它进行了简要的测试。

function scan_ftp_dir($conn, $dir, $pattern) {
    $files = ftp_nlist($conn, $dir);
    if (!$files) {
        return;
    }

    foreach ($files as $file) {
        //the quickest way i can think of to check if is a directory
        if (ftp_size($conn, $file) == -1) {

            //get just the directory name
            $dirName = substr($file, strrpos($file, '/') + 1);

            if (preg_match($pattern, $dirName)) {
                echo $file . ' matched pattern';
            } else {        
                //directory didn't match pattern, recurse   
                scan_ftp_dir($conn, $file, $pattern);
            }
        } 
    }
}

然后做这样的事情

$host = 'localhost';
$user = 'user';
$pass = 'pass';


if (false === ($conn = ftp_connect($host))) {
    die ('cannot connect');
}

if (!ftp_login($conn, $user, $pass)) die ('cannot authenticate');


scan_ftp_dir($conn, '.', '/^beginswith/');

不幸的是,您只能使用ftp_rmdir()删除空目录,但如果查看here,则可以使用一个名为ftp_rmAll()的函数来删除您找到的整个目录结构。

此外,我还在Unix上测试了使用ftp_size()返回的失败状态作为检查ftp_nlist()返回的项目是否为目录的方法的技巧。

答案 1 :(得分:1)

据推测,这个问题不仅仅是第一次出现的问题。

FTP支持DIR列出目录内容,RMDIR删除目录,DEL支持DEL删除文件,因此它支持您需要的操作。

或者您是否在询问如何迭代FTP目录树?

您是否有首选/必需的实施语言?

答案 2 :(得分:0)

嗯,这是我最终使用的脚本。这是一个相当具体的例子,人们必须使用它,但如果你处于我所处的困境,只需输入你的ftp服务器地址,用户名,密码,你想要删除的文件夹的名称,以及要启动的文件夹,这将遍历目录,删除与名称匹配的所有文件夹。如果与服务器的连接中断,则重新连接存在错误,因此如果断开连接,您可能需要再次运行该脚本。


if( $argc == 2 ) {
        $directoryToSearch = $argv[1];
        $host = '';
        $username = '';
        $password = '';
        $connection = connect( $host, $username, $password );
        deleteDirectoriesWithName( $connection, 'directoryToDelete', $directoryToSearch );
        ftp_close( $connection );
        exit( 0 );
}
else {
        cliPrint( "This script currently only supports 1 argument.\n");
        cliPrint( "Usage: php deleteDirectories.php directoryNameToSearch\n");
        exit( 1 );
}

/**
 * Recursively traverse directories and files starting with the path
 * passed in and then delete all directories that match the name
 * passed in
 * @param $connection the connection resource to the database.  
 * @param $name the name of the directories that should be * deleted.
 * @param $path the path to start searching from
 */
function deleteDirectoriesWithName( &$connection, $name, $path ) {
        global $host, $username, $password;
        cliPrint( "At path: $path\n" );
        //Get a list of files in the directory
        $list = ftp_nlist( $connection, $path );
        if ( empty( $list ) ) {
                $rawList = ftp_rawlist( $connection, $path );
                if( empty( $rawList ) ) {
                        cliPrint( "Reconnecting\n");
                        ftp_close( $connection );
                        $connection = connect( $host, $username, $password );
                        cliPrint( "Reconnected\n" );
                        deleteDirectoriesWithName( $connection, $name, $path );
                        return true;
                }

                $pathToPass = addSlashToEnd( $path );
                $list = RawlistToNlist( $rawList, $pathToPass );
        }
        //If we have selected a directory, then 'visit' the files (or directories) in the dir
        if ( $list[0] != $path ) {
                $path = addSlashToEnd( $path );
                //iterate through all of the items listed in the directory
                foreach ( $list as $item ) {
                        //if the directory matches the name to be deleted, delete it recursively
                        if ( $item == $name ) {
                                DeleteDirRecursive( $connection, $path . $item );
                        }

                        //otherwise continue traversing
                        else if ( $item != '..' && $item != '.' ) {
                                deleteDirectoriesWithName( $connection, $name, $path . $item );
                        }
                }
        }
        return true;
}

/**
 *Put output to STDOUT
 */
function cliPrint( $string ) {
        fwrite( STDOUT, $string );
}

/**
 *Connect to the ftp server
 */
function connect( $host, $username, $password ) {
        $connection = ftp_connect( $host );
        if ( !$connection ) {
                die('Could not connect to server: ' . $host );
        }
        $loginSuccessful = ftp_login( $connection, $username, $password );
        if ( !$loginSuccessful ) {
                die( 'Could not login as: ' . $username . '@' . $host );
        }
        cliPrint( "Connection successful\n" );
        return $connection;
}

/**
 *    Delete the provided directory and all its contents from the FTP-server.
 *
 *    @param string $path Path to the directory on the FTP-server relative to
 *    the current working directory
 */
function DeleteDirRecursive(&$resource, $path) {
        global $host, $username, $password;
        cliPrint( $path . "\n" );
        $result_message = "";

        //Get a list of files and directories in the current directory
        $list = ftp_nlist($resource, $path);

        if ( empty($list) ) {
                $listToPass = ftp_rawlist( $resource, $path );
                if ( empty( $listToPass ) ) {
                        cliPrint( "Reconnecting\n" );
                        ftp_close( $resource );
                        $resource = connect( $host, $username, $password );
                        $result_message = "Reconnected\n";
                        cliPrint( "Reconnected\n" );
                        $result_message .= DeleteDirRecursive( $resource, $path );
                        return $result_message;
                }
                $list = RawlistToNlist( $listToPass, addSlashToEnd( $path ) );
        }

        //if the current path is a directory, recursively delete the file within and then
        //delete the empty directory
        if ($list[0] != $path) {
                $path = addSlashToEnd( $path );
                foreach ($list as $item) {
                        if ($item != ".." && $item != ".") {
                                $result_message .= DeleteDirRecursive($resource, $path . $item);
                        }
                }
                cliPrint( 'Delete: ' . $path . "\n" );
                if (ftp_rmdir ($resource, $path)) {

                        cliPrint( "Successfully deleted $path\n" );
                } else {

                        cliPrint( "There was a problem deleting $path\n" );
                }
        }
        //otherwise delete the file
        else {
                cliPrint( 'Delete file: ' . $path . "\n" );
                if (ftp_delete ($resource, $path)) {
                        cliPrint( "Successfully deleted $path\n" );
                } else {

                        cliPrint( "There was a problem deleting $path\n" );
                }
        }
        return $result_message;
}

/**
*    Convert a result from ftp_rawlist() to a result of ftp_nlist()
*
*    @param array $rawlist        Result from ftp_rawlist();
*    @param string $path Path to the directory on the FTP-server relative 
*    to the current working directory
*    @return array An array with the paths of the files in the directory
*/
function RawlistToNlist($rawlist, $path) {
        $array = array();
        foreach ($rawlist as $item) {
                $filename = trim(substr($item, 55, strlen($item) - 55));
                if ($filename != "." || $filename != "..") {
                        $array[] = $filename;
                }
        }
        return $array;
}

/**
 *Adds a '/' to the end of the path if it is not already present.
 */
function addSlashToEnd( $path ) {
        $endOfPath = substr( $path, strlen( $path ) - 1, 1 );
        if( $endOfPath == '/' ) {
                $pathEnding = '';
        }
        else {
                $pathEnding = '/';
        }

        return $path . $pathEnding;
}