如何使用NSURL查看某个文件夹是否是另一个文件夹的子文件?

时间:2017-04-03 20:34:41

标签: objective-c cocoa nsurl

我有// "translate" (push up) index data by model1IndexLen in second model to match new array for (int i=0; i<model2Indices.length; i++) { model2Indices[i] += model1IndexLen; }; NSArray代表一组特殊的父目录。我得到另一个NSURL NSArrayNSURL来代表散布在系统周围的文件。我想知道这些文件是否在我的任何特殊目录或其任何子目录中。 是否有简单/有意的方法来执行此操作,而无需手动解析/遍历绝对URL的路径?

3 个答案:

答案 0 :(得分:3)

NSURL中没有方法可以让您查看另一个NSURL是否代表另一个path的根路径。

一种可能的解决方案是使用URLByStandardizingPath属性将两个URL转换为路径字符串。然后查看一个字符串是否是另一个字符串的前缀。但在获取网址路径之前,请同时使用URLByResolvingSymlinksInPathNSURL *specialURL = ... // a URL for one of the special parent directories NSURL *fileURL = ... // a URL for one of the files to check NSString *specialPath = [specialURL.URLByStandardizingPath.URLByResolvingSymlinksInPath.path stringByAppendingString:@"/"]; NSString *filePath = fileURL.URLByStandardizingPath.URLByResolvingSymlinksInPath.path if ([filePath hasPrefix:specialPath]) { // This file is in this special directory } 来确保结果一致。

示例:

if( $_SERVER['REQUEST_METHOD'] == 'POST' ) {
if( $_POST['template-contactform-email'] != '' ) {

    $name = isset( $_POST['template-contactform-name'] ) ? $_POST['template-contactform-name'] : ''; //navn
    $email = isset( $_POST['template-contactform-email'] ) ? $_POST['template-contactform-email'] : ''; //epost
    $adress = isset( $_POST['template-contactform-email'] ) ? $_POST['template-contactform-email'] : ''; //epost adresse
    $phone = isset( $_POST['template-contactform-phone'] ) ? $_POST['template-contactform-phone'] : ''; //telefonnummer
    $datetime1 = isset( $_POST['template-contactform-datetime'] ) ? $_POST['template-contactform-datetime'] : ''; //dato og tid


    $service = isset( $_POST['template-contactform-service'] ) ? $_POST['template-contactform-service'] : ''; //1
    $service1 = isset( $_POST['template-contactform-service1'] ) ? $_POST['template-contactform-service1'] : ''; //2
    $service2 = isset( $_POST['template-contactform-service2'] ) ? $_POST['template-contactform-service2'] : '';//3
    $message = isset( $_POST['template-contactform-message'] ) ? $_POST['template-contactform-message'] : '';//kundemeldinger.
    //avhukningsbokser
    $checkbox1 = isset( $_POST['checkbox-1'] ) ? $_POST['checkbox-1'] : '';
    $checkbox2 = isset( $_POST['checkbox-2'] ) ? $_POST['checkbox-2'] : '';

    $subject = isset($subject) ? $subject : 'New Message From Contact Form';

    $botcheck = $_POST['template-contactform-botcheck'];

    if( $botcheck == '' ) {

        $mail->SetFrom( $email , $name );
        $mail->AddReplyTo( $email , $name );
        foreach( $toemails as $toemail ) {
            $mail->AddAddress( $toemail['email'] , $toemail['name'] );
        }
        $mail->Subject = "Bestilling fra hjemmeside";

        $name = isset($name) ? "Name: $name<br><br>" : '';
            $adress = isset($adress) ? "Adress:        $adress<br><br>" : '';
        $email = isset($email) ? "Phone:                        $email<br><br>" : '';
        $phone = isset($phone) ? "Telefon:                      $phone<br><br>" : '';
        $datetime1 = isset($datetime1) ? "Dato og tidspunkt:    $datetime1<br><br>" : '';
        $service = isset($service) ? "Additional people:        $service<br><br>" : '';
        $service1 = isset($service1) ? "Sorted waste:           $service1<br><br>" : '';
        $service2 = isset($service2) ? "Payment method:         $service2<br><br>" : '';

        //avhukning start
        $checkbox1 = isset($checkbox1) ? "Papp og tekstil: $checkbox1<br><br>" : '';
        $checkbox2 = isset($checkbox2) ? "Metaller og ror og tilsvarende: $checkbox2<br><br>" : '';

        //avhukning stopp
        $message = isset($message) ? "Additional info:          $message<br><br>" : '';

        $referrer = $_SERVER['HTTP_REFERER'] ? '<br><br><br>Denne eposten kommer fra bestillingskjema via ' . $_SERVER['HTTP_REFERER'] : '';

        $body = "$name $email $phone $datetime1 $service $service1 $service2 $info $checkbox1 $checkbox2<br>$message $referrer";

答案 1 :(得分:2)

一个稍微改进的 Swift 5 版本,结合了 Umair 和 rmaddy 现有优秀答案的优秀功能。

就像 Umair 的回答一样,这正确处理了路径中的文件夹是部分匹配的情况(也就是说,它不会说 /foo/bar-baz/bang 具有 /foo/bar/ 作为祖先)。

它还执行规范化(标准化路径以消除 .../ 之类的内容,并解析符号链接),如 rmaddy 的回答。

func pathHasAncestor(maybeChild: URL, maybeAncestor: URL) -> Bool {
    let ancestorComponents: [String] = canonicalize(maybeAncestor).pathComponents
    let childComponents: [String] = canonicalize(maybeChild).pathComponents

    return ancestorComponents.count < childComponents.count
        && !zip(ancestorComponents, childComponents).contains(where: !=)
}

func canonicalize(_ url: URL) -> URL {
    url.standardizedFileURL.resolvingSymlinksInPath()
}

这是一个非常简单的单元测试来验证基本功能:

import XCTest

class FileUtilsTests: XCTestCase {
    func testPathHasAncestor() throws {
        let leaf = URL(fileURLWithPath: "/foo/bar/baz")
        let parent = leaf.deletingLastPathComponent()
        XCTAssertTrue(pathHasAncestor(maybeChild: leaf, maybeAncestor: parent))
        XCTAssertFalse(pathHasAncestor(maybeChild: URL(fileURLWithPath: "/foo/bar 1/baz"), maybeAncestor: parent))
        XCTAssertFalse(pathHasAncestor(maybeChild: leaf, maybeAncestor: leaf))
    }
}

答案 2 :(得分:1)

前缀解决方案的问题是,它会在以下情况下失败:

PathA: /Documents/untitled folder (1)/SomeFolder/Xyz/Waterfall.mp3
PathB: /Documents/untitled folder

前缀解决方案将告诉您PathA是PathB的子级,尽管不是这种情况。

手动遍历解决方案:

迅速:

extension String {
    func isChildPath(of path: String) -> Bool {
        self.count < path.count
            && !zip(URL(fileURLWithPath: self).pathComponents,
                    URL(fileURLWithPath: path).pathComponents)
                .contains(where: !=)
    }
}

Objective-C:

@interface NSString (Additions)
-(BOOL)isChildOfPath:(NSString *)path;
@end
@implementation NSString (Additions)
-(BOOL)isChildOfPath:(NSString *)path {
   NSString * child = self;
   NSString * parent = path;
   NSArray<NSString *> * childPathComponents = child.pathComponents;
   NSArray<NSString *> * parentPathComponents = parent.pathComponents;
   if (parentPathComponents.count >= childPathComponents.count) {
        return NO;
   }

   for (NSInteger i = 0; i < parentPathComponents.count; i++) {
       NSString * parentComponent = parentPathComponents[i];
       NSString * childComponent = childPathComponents[i];
       if ( ![parentComponent isEqualToString:childComponent] ) {
           return NO;
       }
   }
   return YES;
}
@end