pathier
16class Pathier(pathlib.Path): 17 """Subclasses the standard library pathlib.Path class.""" 18 19 def __new__(cls, *args, **kwargs): 20 if cls is Pathier: 21 cls = WindowsPath if os.name == "nt" else PosixPath 22 self = cls._from_parts(args) 23 if not self._flavour.is_supported: 24 raise NotImplementedError( 25 "cannot instantiate %r on your system" % (cls.__name__,) 26 ) 27 return self 28 29 # ===============================================stats=============================================== 30 @property 31 def dob(self) -> datetime.datetime | None: 32 """Returns the creation date of this file 33 or directory as a dateime.datetime object.""" 34 if self.exists(): 35 return datetime.datetime.fromtimestamp(self.stat().st_ctime) 36 else: 37 return None 38 39 @property 40 def age(self) -> float | None: 41 """Returns the age in seconds of this file or directory.""" 42 if self.exists(): 43 return (datetime.datetime.now() - self.dob).total_seconds() 44 else: 45 return None 46 47 @property 48 def mod_date(self) -> datetime.datetime | None: 49 """Returns the modification date of this file 50 or directory as a datetime.datetime object.""" 51 if self.exists(): 52 return datetime.datetime.fromtimestamp(self.stat().st_mtime) 53 else: 54 return None 55 56 @property 57 def mod_delta(self) -> float | None: 58 """Returns how long ago in seconds this file 59 or directory was modified.""" 60 if self.exists(): 61 return (datetime.datetime.now() - self.mod_date).total_seconds() 62 else: 63 return None 64 65 def size(self, format: bool = False) -> int | str | None: 66 """Returns the size in bytes of this file or directory. 67 Returns None if this path doesn't exist. 68 69 :param format: If True, return value as a formatted string.""" 70 if not self.exists(): 71 return None 72 if self.is_file(): 73 size = self.stat().st_size 74 if self.is_dir(): 75 size = sum(file.stat().st_size for file in self.rglob("*.*")) 76 if format: 77 return self.format_size(size) 78 return size 79 80 @staticmethod 81 def format_size(size: int) -> str: 82 """Format 'size' with common file size abbreviations 83 and rounded to two decimal places. 84 >>> 1234 -> "1.23 kb" """ 85 for unit in ["bytes", "kb", "mb", "gb", "tb", "pb"]: 86 if unit != "bytes": 87 size *= 0.001 88 if size < 1000 or unit == "pb": 89 return f"{round(size, 2)} {unit}" 90 91 def is_larger(self, path: Self) -> bool: 92 """Returns whether this file or folder is larger than 93 the one pointed to by 'path'.""" 94 return self.size() > path.size() 95 96 def is_older(self, path: Self) -> bool: 97 """Returns whether this file or folder is older than 98 the one pointed to by 'path'.""" 99 return self.dob < path.dob 100 101 def modified_more_recently(self, path: Self) -> bool: 102 """Returns whether this file or folder was modified 103 more recently than the one pointed to by 'path'.""" 104 return self.mod_date > path.mod_date 105 106 # ===============================================navigation=============================================== 107 def mkcwd(self): 108 """Make this path your current working directory.""" 109 os.chdir(self) 110 111 @property 112 def in_PATH(self) -> bool: 113 """Return True if this 114 path is in sys.path.""" 115 return str(self) in sys.path 116 117 def add_to_PATH(self, index: int = 0): 118 """Insert this path into sys.path 119 if it isn't already there. 120 121 :param index: The index of sys.path 122 to insert this path at.""" 123 path = str(self) 124 if not self.in_PATH: 125 sys.path.insert(index, path) 126 127 def append_to_PATH(self): 128 """Append this path to sys.path 129 if it isn't already there.""" 130 path = str(self) 131 if not self.in_PATH: 132 sys.path.append(path) 133 134 def remove_from_PATH(self): 135 """Remove this path from sys.path 136 if it's in sys.path.""" 137 if self.in_PATH: 138 sys.path.remove(str(self)) 139 140 def moveup(self, name: str) -> Self: 141 """Return a new Pathier object that is a parent of this instance. 142 'name' is case-sensitive and raises an exception if it isn't in self.parts. 143 >>> p = Pathier("C:\some\directory\in\your\system") 144 >>> print(p.moveup("directory")) 145 >>> "C:\some\directory" 146 >>> print(p.moveup("yeet")) 147 >>> "Exception: yeet is not a parent of C:\some\directory\in\your\system" """ 148 if name not in self.parts: 149 raise Exception(f"{name} is not a parent of {self}") 150 return Pathier(*(self.parts[: self.parts.index(name) + 1])) 151 152 def __sub__(self, levels: int) -> Self: 153 """Return a new Pathier object moved up 'levels' number of parents from the current path. 154 >>> p = Pathier("C:\some\directory\in\your\system") 155 >>> new_p = p - 3 156 >>> print(new_p) 157 >>> "C:\some\directory" """ 158 path = self 159 for _ in range(levels): 160 path = path.parent 161 return path 162 163 def move_under(self, name: str) -> Self: 164 """Return a new Pathier object such that the stem 165 is one level below the folder 'name'. 166 'name' is case-sensitive and raises an exception if it isn't in self.parts. 167 >>> p = Pathier("a/b/c/d/e/f/g") 168 >>> print(p.move_under("c")) 169 >>> 'a/b/c/d'""" 170 if name not in self.parts: 171 raise Exception(f"{name} is not a parent of {self}") 172 return self - (len(self.parts) - self.parts.index(name) - 2) 173 174 def separate(self, name: str, keep_name: bool = False) -> Self: 175 """Return a new Pathier object that is the 176 relative child path after 'name'. 177 'name' is case-sensitive and raises an exception if it isn't in self.parts. 178 179 :param keep_name: If True, the returned path will start with 'name'. 180 >>> p = Pathier("a/b/c/d/e/f/g") 181 >>> print(p.separate("c")) 182 >>> 'd/e/f/g' 183 >>> print(p.separate("c", True)) 184 >>> 'c/d/e/f/g'""" 185 if name not in self.parts: 186 raise Exception(f"{name} is not a parent of {self}") 187 if keep_name: 188 return Pathier(*self.parts[self.parts.index(name) :]) 189 return Pathier(*self.parts[self.parts.index(name) + 1 :]) 190 191 # ============================================write and read============================================ 192 def mkdir(self, mode: int = 511, parents: bool = True, exist_ok: bool = True): 193 """Create this directory. 194 Same as Path().mkdir() except 195 'parents' and 'exist_ok' default 196 to True instead of False.""" 197 super().mkdir(mode, parents, exist_ok) 198 199 def touch(self): 200 """Create file and parents if necessary.""" 201 self.parent.mkdir() 202 super().touch() 203 204 def write_text( 205 self, 206 data: Any, 207 encoding: Any | None = None, 208 errors: Any | None = None, 209 newline: Any | None = None, 210 parents: bool = True, 211 ): 212 """Write data to file. If a TypeError is raised, the function 213 will attempt to case data to a str and try the write again. 214 If a FileNotFoundError is raised and parents = True, 215 self.parent will be created.""" 216 write = functools.partial( 217 super().write_text, 218 encoding=encoding, 219 errors=errors, 220 newline=newline, 221 ) 222 try: 223 write(data) 224 except TypeError: 225 data = str(data) 226 write(data) 227 except FileNotFoundError: 228 if parents: 229 self.parent.mkdir(parents=True) 230 write(data) 231 else: 232 raise 233 except Exception as e: 234 raise 235 236 def write_bytes(self, data: bytes, parents: bool = True): 237 """Write bytes to file. 238 239 :param parents: If True and the write operation fails 240 with a FileNotFoundError, make the parent directory 241 and retry the write.""" 242 try: 243 super().write_bytes(data) 244 except FileNotFoundError: 245 if parents: 246 self.parent.mkdir(parents=True) 247 super().write_bytes(data) 248 else: 249 raise 250 except Exception as e: 251 raise 252 253 def json_loads(self, encoding: Any | None = None, errors: Any | None = None) -> Any: 254 """Load json file.""" 255 return json.loads(self.read_text(encoding, errors)) 256 257 def json_dumps( 258 self, 259 data: Any, 260 encoding: Any | None = None, 261 errors: Any | None = None, 262 newline: Any | None = None, 263 sort_keys: bool = False, 264 indent: Any | None = None, 265 default: Any | None = None, 266 parents: bool = True, 267 ) -> Any: 268 """Dump data to json file.""" 269 self.write_text( 270 json.dumps(data, indent=indent, default=default, sort_keys=sort_keys), 271 encoding, 272 errors, 273 newline, 274 parents, 275 ) 276 277 def toml_loads(self, encoding: Any | None = None, errors: Any | None = None) -> Any: 278 """Load toml file.""" 279 return tomlkit.loads(self.read_text(encoding, errors)) 280 281 def toml_dumps( 282 self, 283 data: Any, 284 encoding: Any | None = None, 285 errors: Any | None = None, 286 newline: Any | None = None, 287 sort_keys: bool = False, 288 parents: bool = True, 289 ): 290 """Dump data to toml file.""" 291 self.write_text( 292 tomlkit.dumps(data, sort_keys), encoding, errors, newline, parents 293 ) 294 295 def loads(self, encoding: Any | None = None, errors: Any | None = None) -> Any: 296 """Load a json or toml file based off this instance's suffix.""" 297 match self.suffix: 298 case ".json": 299 return self.json_loads(encoding, errors) 300 case ".toml": 301 return self.toml_loads(encoding, errors) 302 303 def dumps( 304 self, 305 data: Any, 306 encoding: Any | None = None, 307 errors: Any | None = None, 308 newline: Any | None = None, 309 sort_keys: bool = False, 310 indent: Any | None = None, 311 default: Any | None = None, 312 parents: bool = True, 313 ): 314 """Dump data to a json or toml file based off this instance's suffix.""" 315 match self.suffix: 316 case ".json": 317 self.json_dumps( 318 data, encoding, errors, newline, sort_keys, indent, default, parents 319 ) 320 case ".toml": 321 self.toml_dumps(data, encoding, errors, newline, sort_keys, parents) 322 323 def delete(self, missing_ok: bool = True): 324 """Delete the file or folder pointed to by this instance. 325 Uses self.unlink() if a file and uses shutil.rmtree() if a directory.""" 326 if self.is_file(): 327 self.unlink(missing_ok) 328 elif self.is_dir(): 329 shutil.rmtree(self) 330 331 def copy( 332 self, new_path: Self | pathlib.Path | str, overwrite: bool = False 333 ) -> Self: 334 """Copy the path pointed to by this instance 335 to the instance pointed to by new_path using shutil.copyfile 336 or shutil.copytree. Returns the new path. 337 338 :param new_path: The copy destination. 339 340 :param overwrite: If True, files already existing in new_path 341 will be overwritten. If False, only files that don't exist in new_path 342 will be copied.""" 343 new_path = Pathier(new_path) 344 if self.is_dir(): 345 if overwrite or not new_path.exists(): 346 shutil.copytree(self, new_path, dirs_exist_ok=True) 347 else: 348 files = self.rglob("*.*") 349 for file in files: 350 dst = new_path.with_name(file.name) 351 if not dst.exists(): 352 shutil.copyfile(file, dst) 353 elif self.is_file(): 354 if overwrite or not new_path.exists(): 355 shutil.copyfile(self, new_path) 356 return new_path 357 358 def backup(self, timestamp: bool = False) -> Self | None: 359 """Create a copy of this file or directory with `_backup` appended to the path stem. 360 If the path to be backed up doesn't exist, `None` is returned. 361 Otherwise a `Pathier` object for the backup is returned. 362 363 :param `timestamp`: Add a timestamp to the backup name to prevent overriding previous backups. 364 365 >>> path = Pathier("some_file.txt") 366 >>> path.backup() 367 >>> list(path.iterdir()) 368 >>> ['some_file.txt', 'some_file_backup.txt'] 369 >>> path.backup(True) 370 >>> list(path.iterdir()) 371 >>> ['some_file.txt', 'some_file_backup.txt', 'some_file_backup_04-28-2023-06_25_52_PM.txt']""" 372 if not self.exists(): 373 return None 374 backup_stem = f"{self.stem}_backup" 375 if timestamp: 376 backup_stem = f"{backup_stem}_{datetime.datetime.now().strftime('%m-%d-%Y-%I_%M_%S_%p')}" 377 backup_path = self.with_stem(backup_stem) 378 self.copy(backup_path, True) 379 return backup_path
Subclasses the standard library pathlib.Path class.
Returns the creation date of this file or directory as a dateime.datetime object.
Returns the modification date of this file or directory as a datetime.datetime object.
65 def size(self, format: bool = False) -> int | str | None: 66 """Returns the size in bytes of this file or directory. 67 Returns None if this path doesn't exist. 68 69 :param format: If True, return value as a formatted string.""" 70 if not self.exists(): 71 return None 72 if self.is_file(): 73 size = self.stat().st_size 74 if self.is_dir(): 75 size = sum(file.stat().st_size for file in self.rglob("*.*")) 76 if format: 77 return self.format_size(size) 78 return size
Returns the size in bytes of this file or directory. Returns None if this path doesn't exist.
Parameters
- format: If True, return value as a formatted string.
80 @staticmethod 81 def format_size(size: int) -> str: 82 """Format 'size' with common file size abbreviations 83 and rounded to two decimal places. 84 >>> 1234 -> "1.23 kb" """ 85 for unit in ["bytes", "kb", "mb", "gb", "tb", "pb"]: 86 if unit != "bytes": 87 size *= 0.001 88 if size < 1000 or unit == "pb": 89 return f"{round(size, 2)} {unit}"
Format 'size' with common file size abbreviations and rounded to two decimal places.
>>> 1234 -> "1.23 kb"
91 def is_larger(self, path: Self) -> bool: 92 """Returns whether this file or folder is larger than 93 the one pointed to by 'path'.""" 94 return self.size() > path.size()
Returns whether this file or folder is larger than the one pointed to by 'path'.
96 def is_older(self, path: Self) -> bool: 97 """Returns whether this file or folder is older than 98 the one pointed to by 'path'.""" 99 return self.dob < path.dob
Returns whether this file or folder is older than the one pointed to by 'path'.
101 def modified_more_recently(self, path: Self) -> bool: 102 """Returns whether this file or folder was modified 103 more recently than the one pointed to by 'path'.""" 104 return self.mod_date > path.mod_date
Returns whether this file or folder was modified more recently than the one pointed to by 'path'.
117 def add_to_PATH(self, index: int = 0): 118 """Insert this path into sys.path 119 if it isn't already there. 120 121 :param index: The index of sys.path 122 to insert this path at.""" 123 path = str(self) 124 if not self.in_PATH: 125 sys.path.insert(index, path)
Insert this path into sys.path if it isn't already there.
Parameters
- index: The index of sys.path to insert this path at.
127 def append_to_PATH(self): 128 """Append this path to sys.path 129 if it isn't already there.""" 130 path = str(self) 131 if not self.in_PATH: 132 sys.path.append(path)
Append this path to sys.path if it isn't already there.
134 def remove_from_PATH(self): 135 """Remove this path from sys.path 136 if it's in sys.path.""" 137 if self.in_PATH: 138 sys.path.remove(str(self))
Remove this path from sys.path if it's in sys.path.
140 def moveup(self, name: str) -> Self: 141 """Return a new Pathier object that is a parent of this instance. 142 'name' is case-sensitive and raises an exception if it isn't in self.parts. 143 >>> p = Pathier("C:\some\directory\in\your\system") 144 >>> print(p.moveup("directory")) 145 >>> "C:\some\directory" 146 >>> print(p.moveup("yeet")) 147 >>> "Exception: yeet is not a parent of C:\some\directory\in\your\system" """ 148 if name not in self.parts: 149 raise Exception(f"{name} is not a parent of {self}") 150 return Pathier(*(self.parts[: self.parts.index(name) + 1]))
Return a new Pathier object that is a parent of this instance. 'name' is case-sensitive and raises an exception if it isn't in self.parts.
>>> p = Pathier("C:\some\directory\in\your\system")
>>> print(p.moveup("directory"))
>>> "C:\some\directory"
>>> print(p.moveup("yeet"))
>>> "Exception: yeet is not a parent of C:\some\directory\in\your\system"
163 def move_under(self, name: str) -> Self: 164 """Return a new Pathier object such that the stem 165 is one level below the folder 'name'. 166 'name' is case-sensitive and raises an exception if it isn't in self.parts. 167 >>> p = Pathier("a/b/c/d/e/f/g") 168 >>> print(p.move_under("c")) 169 >>> 'a/b/c/d'""" 170 if name not in self.parts: 171 raise Exception(f"{name} is not a parent of {self}") 172 return self - (len(self.parts) - self.parts.index(name) - 2)
Return a new Pathier object such that the stem is one level below the folder 'name'. 'name' is case-sensitive and raises an exception if it isn't in self.parts.
>>> p = Pathier("a/b/c/d/e/f/g")
>>> print(p.move_under("c"))
>>> 'a/b/c/d'
174 def separate(self, name: str, keep_name: bool = False) -> Self: 175 """Return a new Pathier object that is the 176 relative child path after 'name'. 177 'name' is case-sensitive and raises an exception if it isn't in self.parts. 178 179 :param keep_name: If True, the returned path will start with 'name'. 180 >>> p = Pathier("a/b/c/d/e/f/g") 181 >>> print(p.separate("c")) 182 >>> 'd/e/f/g' 183 >>> print(p.separate("c", True)) 184 >>> 'c/d/e/f/g'""" 185 if name not in self.parts: 186 raise Exception(f"{name} is not a parent of {self}") 187 if keep_name: 188 return Pathier(*self.parts[self.parts.index(name) :]) 189 return Pathier(*self.parts[self.parts.index(name) + 1 :])
Return a new Pathier object that is the relative child path after 'name'. 'name' is case-sensitive and raises an exception if it isn't in self.parts.
Parameters
- keep_name: If True, the returned path will start with 'name'. >>> p = Pathier("a/b/c/d/e/f/g") >>> print(p.separate("c")) >>> 'd/e/f/g' >>> print(p.separate("c", True)) >>> 'c/d/e/f/g'
192 def mkdir(self, mode: int = 511, parents: bool = True, exist_ok: bool = True): 193 """Create this directory. 194 Same as Path().mkdir() except 195 'parents' and 'exist_ok' default 196 to True instead of False.""" 197 super().mkdir(mode, parents, exist_ok)
Create this directory. Same as Path().mkdir() except 'parents' and 'exist_ok' default to True instead of False.
199 def touch(self): 200 """Create file and parents if necessary.""" 201 self.parent.mkdir() 202 super().touch()
Create file and parents if necessary.
204 def write_text( 205 self, 206 data: Any, 207 encoding: Any | None = None, 208 errors: Any | None = None, 209 newline: Any | None = None, 210 parents: bool = True, 211 ): 212 """Write data to file. If a TypeError is raised, the function 213 will attempt to case data to a str and try the write again. 214 If a FileNotFoundError is raised and parents = True, 215 self.parent will be created.""" 216 write = functools.partial( 217 super().write_text, 218 encoding=encoding, 219 errors=errors, 220 newline=newline, 221 ) 222 try: 223 write(data) 224 except TypeError: 225 data = str(data) 226 write(data) 227 except FileNotFoundError: 228 if parents: 229 self.parent.mkdir(parents=True) 230 write(data) 231 else: 232 raise 233 except Exception as e: 234 raise
Write data to file. If a TypeError is raised, the function will attempt to case data to a str and try the write again. If a FileNotFoundError is raised and parents = True, self.parent will be created.
236 def write_bytes(self, data: bytes, parents: bool = True): 237 """Write bytes to file. 238 239 :param parents: If True and the write operation fails 240 with a FileNotFoundError, make the parent directory 241 and retry the write.""" 242 try: 243 super().write_bytes(data) 244 except FileNotFoundError: 245 if parents: 246 self.parent.mkdir(parents=True) 247 super().write_bytes(data) 248 else: 249 raise 250 except Exception as e: 251 raise
Write bytes to file.
Parameters
- parents: If True and the write operation fails with a FileNotFoundError, make the parent directory and retry the write.
253 def json_loads(self, encoding: Any | None = None, errors: Any | None = None) -> Any: 254 """Load json file.""" 255 return json.loads(self.read_text(encoding, errors))
Load json file.
257 def json_dumps( 258 self, 259 data: Any, 260 encoding: Any | None = None, 261 errors: Any | None = None, 262 newline: Any | None = None, 263 sort_keys: bool = False, 264 indent: Any | None = None, 265 default: Any | None = None, 266 parents: bool = True, 267 ) -> Any: 268 """Dump data to json file.""" 269 self.write_text( 270 json.dumps(data, indent=indent, default=default, sort_keys=sort_keys), 271 encoding, 272 errors, 273 newline, 274 parents, 275 )
Dump data to json file.
277 def toml_loads(self, encoding: Any | None = None, errors: Any | None = None) -> Any: 278 """Load toml file.""" 279 return tomlkit.loads(self.read_text(encoding, errors))
Load toml file.
281 def toml_dumps( 282 self, 283 data: Any, 284 encoding: Any | None = None, 285 errors: Any | None = None, 286 newline: Any | None = None, 287 sort_keys: bool = False, 288 parents: bool = True, 289 ): 290 """Dump data to toml file.""" 291 self.write_text( 292 tomlkit.dumps(data, sort_keys), encoding, errors, newline, parents 293 )
Dump data to toml file.
295 def loads(self, encoding: Any | None = None, errors: Any | None = None) -> Any: 296 """Load a json or toml file based off this instance's suffix.""" 297 match self.suffix: 298 case ".json": 299 return self.json_loads(encoding, errors) 300 case ".toml": 301 return self.toml_loads(encoding, errors)
Load a json or toml file based off this instance's suffix.
303 def dumps( 304 self, 305 data: Any, 306 encoding: Any | None = None, 307 errors: Any | None = None, 308 newline: Any | None = None, 309 sort_keys: bool = False, 310 indent: Any | None = None, 311 default: Any | None = None, 312 parents: bool = True, 313 ): 314 """Dump data to a json or toml file based off this instance's suffix.""" 315 match self.suffix: 316 case ".json": 317 self.json_dumps( 318 data, encoding, errors, newline, sort_keys, indent, default, parents 319 ) 320 case ".toml": 321 self.toml_dumps(data, encoding, errors, newline, sort_keys, parents)
Dump data to a json or toml file based off this instance's suffix.
323 def delete(self, missing_ok: bool = True): 324 """Delete the file or folder pointed to by this instance. 325 Uses self.unlink() if a file and uses shutil.rmtree() if a directory.""" 326 if self.is_file(): 327 self.unlink(missing_ok) 328 elif self.is_dir(): 329 shutil.rmtree(self)
Delete the file or folder pointed to by this instance. Uses self.unlink() if a file and uses shutil.rmtree() if a directory.
331 def copy( 332 self, new_path: Self | pathlib.Path | str, overwrite: bool = False 333 ) -> Self: 334 """Copy the path pointed to by this instance 335 to the instance pointed to by new_path using shutil.copyfile 336 or shutil.copytree. Returns the new path. 337 338 :param new_path: The copy destination. 339 340 :param overwrite: If True, files already existing in new_path 341 will be overwritten. If False, only files that don't exist in new_path 342 will be copied.""" 343 new_path = Pathier(new_path) 344 if self.is_dir(): 345 if overwrite or not new_path.exists(): 346 shutil.copytree(self, new_path, dirs_exist_ok=True) 347 else: 348 files = self.rglob("*.*") 349 for file in files: 350 dst = new_path.with_name(file.name) 351 if not dst.exists(): 352 shutil.copyfile(file, dst) 353 elif self.is_file(): 354 if overwrite or not new_path.exists(): 355 shutil.copyfile(self, new_path) 356 return new_path
Copy the path pointed to by this instance to the instance pointed to by new_path using shutil.copyfile or shutil.copytree. Returns the new path.
Parameters
new_path: The copy destination.
overwrite: If True, files already existing in new_path will be overwritten. If False, only files that don't exist in new_path will be copied.
358 def backup(self, timestamp: bool = False) -> Self | None: 359 """Create a copy of this file or directory with `_backup` appended to the path stem. 360 If the path to be backed up doesn't exist, `None` is returned. 361 Otherwise a `Pathier` object for the backup is returned. 362 363 :param `timestamp`: Add a timestamp to the backup name to prevent overriding previous backups. 364 365 >>> path = Pathier("some_file.txt") 366 >>> path.backup() 367 >>> list(path.iterdir()) 368 >>> ['some_file.txt', 'some_file_backup.txt'] 369 >>> path.backup(True) 370 >>> list(path.iterdir()) 371 >>> ['some_file.txt', 'some_file_backup.txt', 'some_file_backup_04-28-2023-06_25_52_PM.txt']""" 372 if not self.exists(): 373 return None 374 backup_stem = f"{self.stem}_backup" 375 if timestamp: 376 backup_stem = f"{backup_stem}_{datetime.datetime.now().strftime('%m-%d-%Y-%I_%M_%S_%p')}" 377 backup_path = self.with_stem(backup_stem) 378 self.copy(backup_path, True) 379 return backup_path
Create a copy of this file or directory with _backup
appended to the path stem.
If the path to be backed up doesn't exist, None
is returned.
Otherwise a Pathier
object for the backup is returned.
Parameters
timestamp
: Add a timestamp to the backup name to prevent overriding previous backups.
>>> path = Pathier("some_file.txt")
>>> path.backup()
>>> list(path.iterdir())
>>> ['some_file.txt', 'some_file_backup.txt']
>>> path.backup(True)
>>> list(path.iterdir())
>>> ['some_file.txt', 'some_file_backup.txt', 'some_file_backup_04-28-2023-06_25_52_PM.txt']
Inherited Members
- pathlib.Path
- cwd
- home
- samefile
- iterdir
- glob
- rglob
- absolute
- resolve
- stat
- owner
- group
- open
- read_bytes
- read_text
- readlink
- chmod
- lchmod
- unlink
- rmdir
- lstat
- rename
- replace
- symlink_to
- hardlink_to
- link_to
- exists
- is_dir
- is_file
- is_mount
- is_symlink
- is_block_device
- is_char_device
- is_fifo
- is_socket
- expanduser
- pathlib.PurePath
- as_posix
- as_uri
- drive
- root
- anchor
- name
- suffix
- suffixes
- stem
- with_name
- with_stem
- with_suffix
- relative_to
- is_relative_to
- parts
- joinpath
- parent
- parents
- is_absolute
- is_reserved
- match