サーバーへの唯一のアクセスが FTP 経由である場合、特定の名前を持つディレクトリ ツリー内のすべてのディレクトリを削除するにはどうすればよいでしょうか。
明確にするために、ディレクトリ ツリーを繰り返し処理し、名前が特定の文字列に一致するすべてのディレクトリを FTP 経由で削除したいと考えています。これを PHP で実装する方法があればいいのですが、どこから始めればよいのでしょうか? また、すでにこれを行うユーティリティを誰かが知っていれば、それも素晴らしいでしょう。
これが開始点です。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()
を見ると、見つかったディレクトリ構造全体を削除するために使用できるという関数があります。ftp_rmAll()
また、Unixでテストしたのは、から返されたアイテムがディレクトリftp_size()
であるかどうかを確認する方法として、から返された失敗ステータスを使用するトリックだけです。ftp_nlist()
おそらく、この質問には、最初に表示された以上のものがあります。
FTP は、ディレクトリの内容を一覧表示する DIR、ディレクトリを削除する RMDIR、ファイルを削除する DEL をサポートしているため、必要な操作をサポートします。
それとも、FTP ディレクトリ ツリーを反復処理する方法を尋ねていますか?
これに適した/必要な実装言語はありますか?
さて、これは私が最終的に使用したスクリプトです。これを使用する必要があるのはかなり具体的な例ですが、私と同じ苦境にある場合は、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;
}