简体   繁体   English

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

[英]Deleting all directories in an FTP archive that have a certain name using PHP

How would one go about deleting all of the directories in a directory tree that have a certain name if the only access to the server available is via FTP? 如果对服务器的唯一访问是通过FTP,那么如何删除目录树中所有具有特定名称的目录?

To clarify, I would like to iterate over a directory tree and delete every directory whose name matches a certain string via FTP. 为了澄清,我想遍历目录树,并通过FTP删除名称与某个字符串匹配的每个目录。 A way to implement this in PHP would be nice - where should I start? 在PHP中实现此方法的方法很好-我应该从哪里开始? Also, if anyone knows of any utilities that would already do this, that would be great as well. 另外,如果有人知道已经可以执行此操作的任何实用程序,那也将是很好的。

Here is a starting point- a function that will scan through an FTP directory and print the name of any directory in the tree which matches the pattern. 这是一个起点,该功能将扫描FTP目录并打印树中与模式匹配的任何目录的名称。 I have tested it briefly. 我已经简要测试过了。

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);
            }
        } 
    }
}

Then do something like this 然后做这样的事情

$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/');

Unfortunately you can only delete an empty directory with ftp_rmdir() , but if you look here there is a function called ftp_rmAll() which you could use to remove whole directory structures which you find. 不幸的是,您只能使用ftp_rmdir()删除一个空目录,但是如果您在此处查看 ,则有一个名为ftp_rmAll()的函数可用于删除找到的整个目录结构。

Also I have only tested on Unix the trick of using the fail status returned from ftp_size() as a method of checking if an item returned by ftp_nlist() is a directory. 另外,我仅在Unix上测试了使用ftp_size()返回的失败状态作为检查ftp_nlist()返回的项是否为目录的方法的技巧。

Presumably there's more to this question than it first appears. 大概这个问题比最初出现的更多。

FTP supports DIR to list directory contents, RMDIR to remove directories and DEL to delete files, so it supports the operations you need. FTP支持DIR列出目录内容,RMDIR删除目录和DEL删除文件,因此它支持您需要的操作。

Or are you asking how to iterate over an FTP directory tree? 还是您在问如何遍历FTP目录树?

Do you have a preferred/required implementation language for this? 您是否有首选/必需的实现语言?

Well, this is the script I ended up using. 好吧,这是我最终使用的脚本。 It's a rather specific instance where one would have to use this, but if you are in the same predicament I was in, simply put in your ftp server address, username, password, the name of the folders you want deleted, and the path of the folder to start in and this will iterate through the directory, deleting all folders that match the name. 这是一个相当具体的实例,在该实例中必须使用它,但是如果您处在与我相同的困境中,只需输入您的ftp服务器地址,用户名,密码,要删除的文件夹的名称以及要开始的文件夹,这将遍历目录,删除所有与名称匹配的文件夹。 There is a bug with reconnecting if the connection to the server is broken so you might need to run the script again if it disconnects. 如果与服务器的连接断开,则重新连接存在一个错误,因此如果断开连接,您可能需要再次运行脚本。


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;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM