简体   繁体   中英

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?

To clarify, I would like to iterate over a directory tree and delete every directory whose name matches a certain string via FTP. A way to implement this in PHP would be nice - where should I start? 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. 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.

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.

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.

Or are you asking how to iterate over an FTP directory tree?

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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