@@ -13,6 +13,10 @@ internal func &(left: UInt32, right: mode_t) -> mode_t {
13
13
}
14
14
#endif
15
15
16
+ #if os(Windows)
17
+ import MSVCRT
18
+ #endif
19
+
16
20
#if !canImport(Darwin) && !os(FreeBSD)
17
21
// The values do not matter as long as they are nonzero.
18
22
fileprivate let UF_IMMUTABLE : Int32 = 1
@@ -406,7 +410,22 @@ open class FileManager : NSObject {
406
410
newAccessDate = providedDate
407
411
}
408
412
#endif
409
-
413
+ case . hidden:
414
+ #if os(Windows)
415
+ let attrs = try windowsFileAttributes ( atPath: path) . dwFileAttributes
416
+ guard let isHidden = attributeValues [ attribute] as? Bool else {
417
+ fatalError ( " Can't set \( attribute) to \( attributeValues [ attribute] as Any ? ) " )
418
+ }
419
+
420
+ let hiddenAttrs = isHidden
421
+ ? attrs | DWORD ( FILE_ATTRIBUTE_HIDDEN)
422
+ : attrs & DWORD ( bitPattern: ~ FILE_ATTRIBUTE_HIDDEN)
423
+ guard path. withCString ( encodedAs: UTF16 . self, { SetFileAttributesW ( $0, hiddenAttrs) } ) else {
424
+ fatalError ( " Couldn't set \( path) to be hidden " )
425
+ }
426
+ #else
427
+ break
428
+ #endif
410
429
case . immutable: fallthrough
411
430
case . _userImmutable:
412
431
prepareToSetOrUnsetFlag ( UF_IMMUTABLE)
@@ -537,7 +556,8 @@ open class FileManager : NSObject {
537
556
538
557
#if os(Windows)
539
558
result [ . deviceIdentifier] = NSNumber ( value: UInt64 ( s. st_rdev) )
540
- let type = FileAttributeType ( attributes: try windowsFileAttributes ( atPath: path) , atPath: path)
559
+ let attributes = try windowsFileAttributes ( atPath: path)
560
+ let type = FileAttributeType ( attributes: attributes, atPath: path)
541
561
#else
542
562
if let pwd = getpwuid ( s. st_uid) , pwd. pointee. pw_name != nil {
543
563
let name = String ( cString: pwd. pointee. pw_name)
@@ -553,6 +573,13 @@ open class FileManager : NSObject {
553
573
#endif
554
574
result [ . type] = type
555
575
576
+ #if os(Windows)
577
+ let attrs = attributes. dwFileAttributes
578
+ result [ . hidden] = attrs & DWORD ( FILE_ATTRIBUTE_HIDDEN) != 0
579
+ #else
580
+ result [ . hidden] = path. first == " . "
581
+ #endif
582
+
556
583
if type == . typeBlockSpecial || type == . typeCharacterSpecial {
557
584
result [ . deviceIdentifier] = NSNumber ( value: UInt64 ( s. st_rdev) )
558
585
}
@@ -1143,6 +1170,7 @@ public struct FileAttributeKey : RawRepresentable, Equatable, Hashable {
1143
1170
public static let extensionHidden = FileAttributeKey ( rawValue: " NSFileExtensionHidden " )
1144
1171
public static let hfsCreatorCode = FileAttributeKey ( rawValue: " NSFileHFSCreatorCode " )
1145
1172
public static let hfsTypeCode = FileAttributeKey ( rawValue: " NSFileHFSTypeCode " )
1173
+ public static let hidden = FileAttributeKey ( rawValue: " NSFileHidden " )
1146
1174
public static let immutable = FileAttributeKey ( rawValue: " NSFileImmutable " )
1147
1175
public static let appendOnly = FileAttributeKey ( rawValue: " NSFileAppendOnly " )
1148
1176
public static let creationDate = FileAttributeKey ( rawValue: " NSFileCreationDate " )
@@ -1169,6 +1197,7 @@ public struct FileAttributeKey : RawRepresentable, Equatable, Hashable {
1169
1197
. extensionHidden,
1170
1198
. hfsCreatorCode,
1171
1199
. hfsTypeCode,
1200
+ . hidden,
1172
1201
. immutable,
1173
1202
. appendOnly,
1174
1203
. creationDate,
0 commit comments