1 //! Cross-platform path manipulation.
3 //! This module provides two types, [`PathBuf`] and [`Path`] (akin to [`String`]
4 //! and [`str`]), for working with paths abstractly. These types are thin wrappers
5 //! around [`OsString`] and [`OsStr`] respectively, meaning that they work directly
6 //! on strings according to the local platform's path syntax.
8 //! Paths can be parsed into [`Component`]s by iterating over the structure
9 //! returned by the [`components`] method on [`Path`]. [`Component`]s roughly
10 //! correspond to the substrings between path separators (`/` or `\`). You can
11 //! reconstruct an equivalent path from components with the [`push`] method on
12 //! [`PathBuf`]; note that the paths may differ syntactically by the
13 //! normalization described in the documentation for the [`components`] method.
15 //! ## Case sensitivity
17 //! Unless otherwise indicated path methods that do not access the filesystem,
18 //! such as [`Path::starts_with`] and [`Path::ends_with`], are case sensitive no
19 //! matter the platform or filesystem. An exception to this is made for Windows
24 //! Path manipulation includes both parsing components from slices and building
27 //! To parse a path, you can create a [`Path`] slice from a [`str`]
28 //! slice and start asking questions:
31 //! use std::path::Path;
32 //! use std::ffi::OsStr;
34 //! let path = Path::new("/tmp/foo/bar.txt");
36 //! let parent = path.parent();
37 //! assert_eq!(parent, Some(Path::new("/tmp/foo")));
39 //! let file_stem = path.file_stem();
40 //! assert_eq!(file_stem, Some(OsStr::new("bar")));
42 //! let extension = path.extension();
43 //! assert_eq!(extension, Some(OsStr::new("txt")));
46 //! To build or modify paths, use [`PathBuf`]:
49 //! use std::path::PathBuf;
51 //! // This way works...
52 //! let mut path = PathBuf::from("c:\\");
54 //! path.push("windows");
55 //! path.push("system32");
57 //! path.set_extension("dll");
59 //! // ... but push is best used if you don't know everything up
60 //! // front. If you do, this way is better:
61 //! let path: PathBuf = ["c:\\", "windows", "system32.dll"].iter().collect();
64 //! [`components`]: Path::components
65 //! [`push`]: PathBuf::push
67 #![stable(feature = "rust1", since = "1.0.0")]
68 #![deny(unsafe_op_in_unsafe_fn)]
73 use crate::borrow
::{Borrow, Cow}
;
75 use crate::collections
::TryReserveError
;
76 use crate::error
::Error
;
79 use crate::hash
::{Hash, Hasher}
;
81 use crate::iter
::FusedIterator
;
82 use crate::ops
::{self, Deref}
;
84 use crate::str::FromStr
;
87 use crate::ffi
::{OsStr, OsString}
;
89 use crate::sys
::path
::{is_sep_byte, is_verbatim_sep, parse_prefix, MAIN_SEP_STR}
;
91 ////////////////////////////////////////////////////////////////////////////////
93 ////////////////////////////////////////////////////////////////////////////////
95 // Parsing in this module is done by directly transmuting OsStr to [u8] slices,
96 // taking advantage of the fact that OsStr always encodes ASCII characters
97 // as-is. Eventually, this transmutation should be replaced by direct uses of
98 // OsStr APIs for parsing, but it will take a while for those to become
101 ////////////////////////////////////////////////////////////////////////////////
103 ////////////////////////////////////////////////////////////////////////////////
105 /// Windows path prefixes, e.g., `C:` or `\\server\share`.
107 /// Windows uses a variety of path prefix styles, including references to drive
108 /// volumes (like `C:`), network shared folders (like `\\server\share`), and
109 /// others. In addition, some path prefixes are "verbatim" (i.e., prefixed with
110 /// `\\?\`), in which case `/` is *not* treated as a separator and essentially
111 /// no normalization is performed.
116 /// use std::path::{Component, Path, Prefix};
117 /// use std::path::Prefix::*;
118 /// use std::ffi::OsStr;
120 /// fn get_path_prefix(s: &str) -> Prefix<'_> {
121 /// let path = Path::new(s);
122 /// match path.components().next().unwrap() {
123 /// Component::Prefix(prefix_component) => prefix_component.kind(),
128 /// # if cfg!(windows) {
129 /// assert_eq!(Verbatim(OsStr::new("pictures")),
130 /// get_path_prefix(r"\\?\pictures\kittens"));
131 /// assert_eq!(VerbatimUNC(OsStr::new("server"), OsStr::new("share")),
132 /// get_path_prefix(r"\\?\UNC\server\share"));
133 /// assert_eq!(VerbatimDisk(b'C'), get_path_prefix(r"\\?\c:\"));
134 /// assert_eq!(DeviceNS(OsStr::new("BrainInterface")),
135 /// get_path_prefix(r"\\.\BrainInterface"));
136 /// assert_eq!(UNC(OsStr::new("server"), OsStr::new("share")),
137 /// get_path_prefix(r"\\server\share"));
138 /// assert_eq!(Disk(b'C'), get_path_prefix(r"C:\Users\Rust\Pictures\Ferris"));
141 #[derive(Copy, Clone, Debug, Hash, PartialOrd, Ord, PartialEq, Eq)]
142 #[stable(feature = "rust1", since = "1.0.0")]
143 pub enum Prefix
<'a
> {
144 /// Verbatim prefix, e.g., `\\?\cat_pics`.
146 /// Verbatim prefixes consist of `\\?\` immediately followed by the given
148 #[stable(feature = "rust1", since = "1.0.0")]
149 Verbatim(#[stable(feature = "rust1", since = "1.0.0")] &'a OsStr),
151 /// Verbatim prefix using Windows' _**U**niform **N**aming **C**onvention_,
152 /// e.g., `\\?\UNC\server\share`.
154 /// Verbatim UNC prefixes consist of `\\?\UNC\` immediately followed by the
155 /// server's hostname and a share name.
156 #[stable(feature = "rust1", since = "1.0.0")]
158 #[stable(feature = "rust1", since = "1.0.0")] &'a OsStr,
159 #[stable(feature = "rust1", since = "1.0.0")] &'a OsStr,
162 /// Verbatim disk prefix, e.g., `\\?\C:`.
164 /// Verbatim disk prefixes consist of `\\?\` immediately followed by the
165 /// drive letter and `:`.
166 #[stable(feature = "rust1", since = "1.0.0")]
167 VerbatimDisk(#[stable(feature = "rust1", since = "1.0.0")] u8),
169 /// Device namespace prefix, e.g., `\\.\COM42`.
171 /// Device namespace prefixes consist of `\\.\` (possibly using `/`
172 /// instead of `\`), immediately followed by the device name.
173 #[stable(feature = "rust1", since = "1.0.0")]
174 DeviceNS(#[stable(feature = "rust1", since = "1.0.0")] &'a OsStr),
176 /// Prefix using Windows' _**U**niform **N**aming **C**onvention_, e.g.
177 /// `\\server\share`.
179 /// UNC prefixes consist of the server's hostname and a share name.
180 #[stable(feature = "rust1", since = "1.0.0")]
182 #[stable(feature = "rust1", since = "1.0.0")] &'a OsStr,
183 #[stable(feature = "rust1", since = "1.0.0")] &'a OsStr,
186 /// Prefix `C:` for the given disk drive.
187 #[stable(feature = "rust1", since = "1.0.0")]
188 Disk(#[stable(feature = "rust1", since = "1.0.0")] u8),
191 impl<'a
> Prefix
<'a
> {
193 fn len(&self) -> usize {
195 fn os_str_len(s
: &OsStr
) -> usize {
196 s
.as_encoded_bytes().len()
199 Verbatim(x
) => 4 + os_str_len(x
),
200 VerbatimUNC(x
, y
) => {
201 8 + os_str_len(x
) + if os_str_len(y
) > 0 { 1 + os_str_len(y) }
else { 0 }
203 VerbatimDisk(_
) => 6,
204 UNC(x
, y
) => 2 + os_str_len(x
) + if os_str_len(y
) > 0 { 1 + os_str_len(y) }
else { 0 }
,
205 DeviceNS(x
) => 4 + os_str_len(x
),
210 /// Determines if the prefix is verbatim, i.e., begins with `\\?\`.
215 /// use std::path::Prefix::*;
216 /// use std::ffi::OsStr;
218 /// assert!(Verbatim(OsStr::new("pictures")).is_verbatim());
219 /// assert!(VerbatimUNC(OsStr::new("server"), OsStr::new("share")).is_verbatim());
220 /// assert!(VerbatimDisk(b'C').is_verbatim());
221 /// assert!(!DeviceNS(OsStr::new("BrainInterface")).is_verbatim());
222 /// assert!(!UNC(OsStr::new("server"), OsStr::new("share")).is_verbatim());
223 /// assert!(!Disk(b'C').is_verbatim());
227 #[stable(feature = "rust1", since = "1.0.0")]
228 pub fn is_verbatim(&self) -> bool
{
230 matches
!(*self, Verbatim(_
) | VerbatimDisk(_
) | VerbatimUNC(..))
234 fn is_drive(&self) -> bool
{
235 matches
!(*self, Prefix
::Disk(_
))
239 fn has_implicit_root(&self) -> bool
{
244 ////////////////////////////////////////////////////////////////////////////////
245 // Exposed parsing helpers
246 ////////////////////////////////////////////////////////////////////////////////
248 /// Determines whether the character is one of the permitted path
249 /// separators for the current platform.
256 /// assert!(path::is_separator('/')); // '/' works for both Unix and Windows
257 /// assert!(!path::is_separator('❤'));
260 #[stable(feature = "rust1", since = "1.0.0")]
261 pub fn is_separator(c
: char) -> bool
{
262 c
.is_ascii() && is_sep_byte(c
as u8)
265 /// The primary separator of path components for the current platform.
267 /// For example, `/` on Unix and `\` on Windows.
268 #[stable(feature = "rust1", since = "1.0.0")]
269 pub const MAIN_SEPARATOR
: char = crate::sys
::path
::MAIN_SEP
;
271 /// The primary separator of path components for the current platform.
273 /// For example, `/` on Unix and `\` on Windows.
274 #[stable(feature = "main_separator_str", since = "1.68.0")]
275 pub const MAIN_SEPARATOR_STR
: &str = crate::sys
::path
::MAIN_SEP_STR
;
277 ////////////////////////////////////////////////////////////////////////////////
279 ////////////////////////////////////////////////////////////////////////////////
281 // Iterate through `iter` while it matches `prefix`; return `None` if `prefix`
282 // is not a prefix of `iter`, otherwise return `Some(iter_after_prefix)` giving
283 // `iter` after having exhausted `prefix`.
284 fn iter_after
<'a
, 'b
, I
, J
>(mut iter
: I
, mut prefix
: J
) -> Option
<I
>
286 I
: Iterator
<Item
= Component
<'a
>> + Clone
,
287 J
: Iterator
<Item
= Component
<'b
>>,
290 let mut iter_next
= iter
.clone();
291 match (iter_next
.next(), prefix
.next()) {
292 (Some(ref x
), Some(ref y
)) if x
== y
=> (),
293 (Some(_
), Some(_
)) => return None
,
294 (Some(_
), None
) => return Some(iter
),
295 (None
, None
) => return Some(iter
),
296 (None
, Some(_
)) => return None
,
302 // Detect scheme on Redox
303 fn has_redox_scheme(s
: &[u8]) -> bool
{
304 cfg
!(target_os
= "redox") && s
.contains(&b'
:'
)
307 ////////////////////////////////////////////////////////////////////////////////
308 // Cross-platform, iterator-independent parsing
309 ////////////////////////////////////////////////////////////////////////////////
311 /// Says whether the first byte after the prefix is a separator.
312 fn has_physical_root(s
: &[u8], prefix
: Option
<Prefix
<'_
>>) -> bool
{
313 let path
= if let Some(p
) = prefix { &s[p.len()..] }
else { s }
;
314 !path
.is_empty() && is_sep_byte(path
[0])
317 // basic workhorse for splitting stem and extension
318 fn rsplit_file_at_dot(file
: &OsStr
) -> (Option
<&OsStr
>, Option
<&OsStr
>) {
319 if file
.as_encoded_bytes() == b
".." {
320 return (Some(file
), None
);
323 // The unsafety here stems from converting between &OsStr and &[u8]
324 // and back. This is safe to do because (1) we only look at ASCII
325 // contents of the encoding and (2) new &OsStr values are produced
326 // only from ASCII-bounded slices of existing &OsStr values.
327 let mut iter
= file
.as_encoded_bytes().rsplitn(2, |b
| *b
== b'
.'
);
328 let after
= iter
.next();
329 let before
= iter
.next();
330 if before
== Some(b
"") {
335 before
.map(|s
| OsStr
::from_encoded_bytes_unchecked(s
)),
336 after
.map(|s
| OsStr
::from_encoded_bytes_unchecked(s
)),
342 fn split_file_at_dot(file
: &OsStr
) -> (&OsStr
, Option
<&OsStr
>) {
343 let slice
= file
.as_encoded_bytes();
348 // The unsafety here stems from converting between &OsStr and &[u8]
349 // and back. This is safe to do because (1) we only look at ASCII
350 // contents of the encoding and (2) new &OsStr values are produced
351 // only from ASCII-bounded slices of existing &OsStr values.
352 let i
= match slice
[1..].iter().position(|b
| *b
== b'
.'
) {
354 None
=> return (file
, None
),
356 let before
= &slice
[..i
];
357 let after
= &slice
[i
+ 1..];
360 OsStr
::from_encoded_bytes_unchecked(before
),
361 Some(OsStr
::from_encoded_bytes_unchecked(after
)),
366 ////////////////////////////////////////////////////////////////////////////////
367 // The core iterators
368 ////////////////////////////////////////////////////////////////////////////////
370 /// Component parsing works by a double-ended state machine; the cursors at the
371 /// front and back of the path each keep track of what parts of the path have
372 /// been consumed so far.
374 /// Going front to back, a path is made up of a prefix, a starting
375 /// directory component, and a body (of normal components)
376 #[derive(Copy, Clone, PartialEq, PartialOrd, Debug)]
379 StartDir
= 1, // / or . or nothing
380 Body
= 2, // foo/bar/baz
384 /// A structure wrapping a Windows path prefix as well as its unparsed string
387 /// In addition to the parsed [`Prefix`] information returned by [`kind`],
388 /// `PrefixComponent` also holds the raw and unparsed [`OsStr`] slice,
389 /// returned by [`as_os_str`].
391 /// Instances of this `struct` can be obtained by matching against the
392 /// [`Prefix` variant] on [`Component`].
394 /// Does not occur on Unix.
399 /// # if cfg!(windows) {
400 /// use std::path::{Component, Path, Prefix};
401 /// use std::ffi::OsStr;
403 /// let path = Path::new(r"c:\you\later\");
404 /// match path.components().next().unwrap() {
405 /// Component::Prefix(prefix_component) => {
406 /// assert_eq!(Prefix::Disk(b'C'), prefix_component.kind());
407 /// assert_eq!(OsStr::new("c:"), prefix_component.as_os_str());
409 /// _ => unreachable!(),
414 /// [`as_os_str`]: PrefixComponent::as_os_str
415 /// [`kind`]: PrefixComponent::kind
416 /// [`Prefix` variant]: Component::Prefix
417 #[stable(feature = "rust1", since = "1.0.0")]
418 #[derive(Copy, Clone, Eq, Debug)]
419 pub struct PrefixComponent
<'a
> {
420 /// The prefix as an unparsed `OsStr` slice.
423 /// The parsed prefix data.
427 impl<'a
> PrefixComponent
<'a
> {
428 /// Returns the parsed prefix data.
430 /// See [`Prefix`]'s documentation for more information on the different
431 /// kinds of prefixes.
432 #[stable(feature = "rust1", since = "1.0.0")]
435 pub fn kind(&self) -> Prefix
<'a
> {
439 /// Returns the raw [`OsStr`] slice for this prefix.
440 #[stable(feature = "rust1", since = "1.0.0")]
443 pub fn as_os_str(&self) -> &'a OsStr
{
448 #[stable(feature = "rust1", since = "1.0.0")]
449 impl<'a
> PartialEq
for PrefixComponent
<'a
> {
451 fn eq(&self, other
: &PrefixComponent
<'a
>) -> bool
{
452 self.parsed
== other
.parsed
456 #[stable(feature = "rust1", since = "1.0.0")]
457 impl<'a
> PartialOrd
for PrefixComponent
<'a
> {
459 fn partial_cmp(&self, other
: &PrefixComponent
<'a
>) -> Option
<cmp
::Ordering
> {
460 PartialOrd
::partial_cmp(&self.parsed
, &other
.parsed
)
464 #[stable(feature = "rust1", since = "1.0.0")]
465 impl Ord
for PrefixComponent
<'_
> {
467 fn cmp(&self, other
: &Self) -> cmp
::Ordering
{
468 Ord
::cmp(&self.parsed
, &other
.parsed
)
472 #[stable(feature = "rust1", since = "1.0.0")]
473 impl Hash
for PrefixComponent
<'_
> {
474 fn hash
<H
: Hasher
>(&self, h
: &mut H
) {
479 /// A single component of a path.
481 /// A `Component` roughly corresponds to a substring between path separators
484 /// This `enum` is created by iterating over [`Components`], which in turn is
485 /// created by the [`components`](Path::components) method on [`Path`].
490 /// use std::path::{Component, Path};
492 /// let path = Path::new("/tmp/foo/bar.txt");
493 /// let components = path.components().collect::<Vec<_>>();
494 /// assert_eq!(&components, &[
495 /// Component::RootDir,
496 /// Component::Normal("tmp".as_ref()),
497 /// Component::Normal("foo".as_ref()),
498 /// Component::Normal("bar.txt".as_ref()),
501 #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
502 #[stable(feature = "rust1", since = "1.0.0")]
503 pub enum Component
<'a
> {
504 /// A Windows path prefix, e.g., `C:` or `\\server\share`.
506 /// There is a large variety of prefix types, see [`Prefix`]'s documentation
509 /// Does not occur on Unix.
510 #[stable(feature = "rust1", since = "1.0.0")]
511 Prefix(#[stable(feature = "rust1", since = "1.0.0")] PrefixComponent<'a>),
513 /// The root directory component, appears after any prefix and before anything else.
515 /// It represents a separator that designates that a path starts from root.
516 #[stable(feature = "rust1", since = "1.0.0")]
519 /// A reference to the current directory, i.e., `.`.
520 #[stable(feature = "rust1", since = "1.0.0")]
523 /// A reference to the parent directory, i.e., `..`.
524 #[stable(feature = "rust1", since = "1.0.0")]
527 /// A normal component, e.g., `a` and `b` in `a/b`.
529 /// This variant is the most common one, it represents references to files
531 #[stable(feature = "rust1", since = "1.0.0")]
532 Normal(#[stable(feature = "rust1", since = "1.0.0")] &'a OsStr),
535 impl<'a
> Component
<'a
> {
536 /// Extracts the underlying [`OsStr`] slice.
541 /// use std::path::Path;
543 /// let path = Path::new("./tmp/foo/bar.txt");
544 /// let components: Vec<_> = path.components().map(|comp| comp.as_os_str()).collect();
545 /// assert_eq!(&components, &[".", "tmp", "foo", "bar.txt"]);
547 #[must_use = "`self` will be dropped if the result is not used"]
548 #[stable(feature = "rust1", since = "1.0.0")]
549 pub fn as_os_str(self) -> &'a OsStr
{
551 Component
::Prefix(p
) => p
.as_os_str(),
552 Component
::RootDir
=> OsStr
::new(MAIN_SEP_STR
),
553 Component
::CurDir
=> OsStr
::new("."),
554 Component
::ParentDir
=> OsStr
::new(".."),
555 Component
::Normal(path
) => path
,
560 #[stable(feature = "rust1", since = "1.0.0")]
561 impl AsRef
<OsStr
> for Component
<'_
> {
563 fn as_ref(&self) -> &OsStr
{
568 #[stable(feature = "path_component_asref", since = "1.25.0")]
569 impl AsRef
<Path
> for Component
<'_
> {
571 fn as_ref(&self) -> &Path
{
572 self.as_os_str().as_ref()
576 /// An iterator over the [`Component`]s of a [`Path`].
578 /// This `struct` is created by the [`components`] method on [`Path`].
579 /// See its documentation for more.
584 /// use std::path::Path;
586 /// let path = Path::new("/tmp/foo/bar.txt");
588 /// for component in path.components() {
589 /// println!("{component:?}");
593 /// [`components`]: Path::components
595 #[must_use = "iterators are lazy and do nothing unless consumed"]
596 #[stable(feature = "rust1", since = "1.0.0")]
597 pub struct Components
<'a
> {
598 // The path left to parse components from
601 // The prefix as it was originally parsed, if any
602 prefix
: Option
<Prefix
<'a
>>,
604 // true if path *physically* has a root separator; for most Windows
605 // prefixes, it may have a "logical" root separator for the purposes of
606 // normalization, e.g., \\server\share == \\server\share\.
607 has_physical_root
: bool
,
609 // The iterator is double-ended, and these two states keep track of what has
610 // been produced from either end
615 /// An iterator over the [`Component`]s of a [`Path`], as [`OsStr`] slices.
617 /// This `struct` is created by the [`iter`] method on [`Path`].
618 /// See its documentation for more.
620 /// [`iter`]: Path::iter
622 #[must_use = "iterators are lazy and do nothing unless consumed"]
623 #[stable(feature = "rust1", since = "1.0.0")]
624 pub struct Iter
<'a
> {
625 inner
: Components
<'a
>,
628 #[stable(feature = "path_components_debug", since = "1.13.0")]
629 impl fmt
::Debug
for Components
<'_
> {
630 fn fmt(&self, f
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
631 struct DebugHelper
<'a
>(&'a Path
);
633 impl fmt
::Debug
for DebugHelper
<'_
> {
634 fn fmt(&self, f
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
635 f
.debug_list().entries(self.0.components()).finish()
639 f
.debug_tuple("Components").field(&DebugHelper(self.as_path())).finish()
643 impl<'a
> Components
<'a
> {
644 // how long is the prefix, if any?
646 fn prefix_len(&self) -> usize {
647 self.prefix
.as_ref().map(Prefix
::len
).unwrap_or(0)
651 fn prefix_verbatim(&self) -> bool
{
652 self.prefix
.as_ref().map(Prefix
::is_verbatim
).unwrap_or(false)
655 /// how much of the prefix is left from the point of view of iteration?
657 fn prefix_remaining(&self) -> usize {
658 if self.front
== State
::Prefix { self.prefix_len() }
else { 0 }
661 // Given the iteration so far, how much of the pre-State::Body path is left?
663 fn len_before_body(&self) -> usize {
664 let root
= if self.front
<= State
::StartDir
&& self.has_physical_root { 1 }
else { 0 }
;
665 let cur_dir
= if self.front
<= State
::StartDir
&& self.include_cur_dir() { 1 }
else { 0 }
;
666 self.prefix_remaining() + root
+ cur_dir
669 // is the iteration complete?
671 fn finished(&self) -> bool
{
672 self.front
== State
::Done
|| self.back
== State
::Done
|| self.front
> self.back
676 fn is_sep_byte(&self, b
: u8) -> bool
{
677 if self.prefix_verbatim() { is_verbatim_sep(b) }
else { is_sep_byte(b) }
680 /// Extracts a slice corresponding to the portion of the path remaining for iteration.
685 /// use std::path::Path;
687 /// let mut components = Path::new("/tmp/foo/bar.txt").components();
688 /// components.next();
689 /// components.next();
691 /// assert_eq!(Path::new("foo/bar.txt"), components.as_path());
694 #[stable(feature = "rust1", since = "1.0.0")]
695 pub fn as_path(&self) -> &'a Path
{
696 let mut comps
= self.clone();
697 if comps
.front
== State
::Body
{
700 if comps
.back
== State
::Body
{
703 unsafe { Path::from_u8_slice(comps.path) }
706 /// Is the *original* path rooted?
707 fn has_root(&self) -> bool
{
708 if self.has_physical_root
{
711 if let Some(p
) = self.prefix
{
712 if p
.has_implicit_root() {
719 /// Should the normalized path include a leading . ?
720 fn include_cur_dir(&self) -> bool
{
724 let mut iter
= self.path
[self.prefix_remaining()..].iter();
725 match (iter
.next(), iter
.next()) {
726 (Some(&b'
.'
), None
) => true,
727 (Some(&b'
.'
), Some(&b
)) => self.is_sep_byte(b
),
732 // parse a given byte sequence following the OsStr encoding into the
733 // corresponding path component
734 unsafe fn parse_single_component
<'b
>(&self, comp
: &'b
[u8]) -> Option
<Component
<'b
>> {
736 b
"." if self.prefix_verbatim() => Some(Component
::CurDir
),
737 b
"." => None
, // . components are normalized away, except at
738 // the beginning of a path, which is treated
739 // separately via `include_cur_dir`
740 b
".." => Some(Component
::ParentDir
),
742 _
=> Some(Component
::Normal(unsafe { OsStr::from_encoded_bytes_unchecked(comp) }
)),
746 // parse a component from the left, saying how many bytes to consume to
747 // remove the component
748 fn parse_next_component(&self) -> (usize, Option
<Component
<'a
>>) {
749 debug_assert
!(self.front
== State
::Body
);
750 let (extra
, comp
) = match self.path
.iter().position(|b
| self.is_sep_byte(*b
)) {
751 None
=> (0, self.path
),
752 Some(i
) => (1, &self.path
[..i
]),
754 // SAFETY: `comp` is a valid substring, since it is split on a separator.
755 (comp
.len() + extra
, unsafe { self.parse_single_component(comp) }
)
758 // parse a component from the right, saying how many bytes to consume to
759 // remove the component
760 fn parse_next_component_back(&self) -> (usize, Option
<Component
<'a
>>) {
761 debug_assert
!(self.back
== State
::Body
);
762 let start
= self.len_before_body();
763 let (extra
, comp
) = match self.path
[start
..].iter().rposition(|b
| self.is_sep_byte(*b
)) {
764 None
=> (0, &self.path
[start
..]),
765 Some(i
) => (1, &self.path
[start
+ i
+ 1..]),
767 // SAFETY: `comp` is a valid substring, since it is split on a separator.
768 (comp
.len() + extra
, unsafe { self.parse_single_component(comp) }
)
771 // trim away repeated separators (i.e., empty components) on the left
772 fn trim_left(&mut self) {
773 while !self.path
.is_empty() {
774 let (size
, comp
) = self.parse_next_component();
778 self.path
= &self.path
[size
..];
783 // trim away repeated separators (i.e., empty components) on the right
784 fn trim_right(&mut self) {
785 while self.path
.len() > self.len_before_body() {
786 let (size
, comp
) = self.parse_next_component_back();
790 self.path
= &self.path
[..self.path
.len() - size
];
796 #[stable(feature = "rust1", since = "1.0.0")]
797 impl AsRef
<Path
> for Components
<'_
> {
799 fn as_ref(&self) -> &Path
{
804 #[stable(feature = "rust1", since = "1.0.0")]
805 impl AsRef
<OsStr
> for Components
<'_
> {
807 fn as_ref(&self) -> &OsStr
{
808 self.as_path().as_os_str()
812 #[stable(feature = "path_iter_debug", since = "1.13.0")]
813 impl fmt
::Debug
for Iter
<'_
> {
814 fn fmt(&self, f
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
815 struct DebugHelper
<'a
>(&'a Path
);
817 impl fmt
::Debug
for DebugHelper
<'_
> {
818 fn fmt(&self, f
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
819 f
.debug_list().entries(self.0.iter
()).finish()
823 f
.debug_tuple("Iter").field(&DebugHelper(self.as_path())).finish()
828 /// Extracts a slice corresponding to the portion of the path remaining for iteration.
833 /// use std::path::Path;
835 /// let mut iter = Path::new("/tmp/foo/bar.txt").iter();
839 /// assert_eq!(Path::new("foo/bar.txt"), iter.as_path());
841 #[stable(feature = "rust1", since = "1.0.0")]
844 pub fn as_path(&self) -> &'a Path
{
849 #[stable(feature = "rust1", since = "1.0.0")]
850 impl AsRef
<Path
> for Iter
<'_
> {
852 fn as_ref(&self) -> &Path
{
857 #[stable(feature = "rust1", since = "1.0.0")]
858 impl AsRef
<OsStr
> for Iter
<'_
> {
860 fn as_ref(&self) -> &OsStr
{
861 self.as_path().as_os_str()
865 #[stable(feature = "rust1", since = "1.0.0")]
866 impl<'a
> Iterator
for Iter
<'a
> {
867 type Item
= &'a OsStr
;
870 fn next(&mut self) -> Option
<&'a OsStr
> {
871 self.inner
.next().map(Component
::as_os_str
)
875 #[stable(feature = "rust1", since = "1.0.0")]
876 impl<'a
> DoubleEndedIterator
for Iter
<'a
> {
878 fn next_back(&mut self) -> Option
<&'a OsStr
> {
879 self.inner
.next_back().map(Component
::as_os_str
)
883 #[stable(feature = "fused", since = "1.26.0")]
884 impl FusedIterator
for Iter
<'_
> {}
886 #[stable(feature = "rust1", since = "1.0.0")]
887 impl<'a
> Iterator
for Components
<'a
> {
888 type Item
= Component
<'a
>;
890 fn next(&mut self) -> Option
<Component
<'a
>> {
891 while !self.finished() {
893 State
::Prefix
if self.prefix_len() > 0 => {
894 self.front
= State
::StartDir
;
895 debug_assert
!(self.prefix_len() <= self.path
.len());
896 let raw
= &self.path
[..self.prefix_len()];
897 self.path
= &self.path
[self.prefix_len()..];
898 return Some(Component
::Prefix(PrefixComponent
{
899 raw
: unsafe { OsStr::from_encoded_bytes_unchecked(raw) }
,
900 parsed
: self.prefix
.unwrap(),
904 self.front
= State
::StartDir
;
907 self.front
= State
::Body
;
908 if self.has_physical_root
{
909 debug_assert
!(!self.path
.is_empty());
910 self.path
= &self.path
[1..];
911 return Some(Component
::RootDir
);
912 } else if let Some(p
) = self.prefix
{
913 if p
.has_implicit_root() && !p
.is_verbatim() {
914 return Some(Component
::RootDir
);
916 } else if self.include_cur_dir() {
917 debug_assert
!(!self.path
.is_empty());
918 self.path
= &self.path
[1..];
919 return Some(Component
::CurDir
);
922 State
::Body
if !self.path
.is_empty() => {
923 let (size
, comp
) = self.parse_next_component();
924 self.path
= &self.path
[size
..];
930 self.front
= State
::Done
;
932 State
::Done
=> unreachable
!(),
939 #[stable(feature = "rust1", since = "1.0.0")]
940 impl<'a
> DoubleEndedIterator
for Components
<'a
> {
941 fn next_back(&mut self) -> Option
<Component
<'a
>> {
942 while !self.finished() {
944 State
::Body
if self.path
.len() > self.len_before_body() => {
945 let (size
, comp
) = self.parse_next_component_back();
946 self.path
= &self.path
[..self.path
.len() - size
];
952 self.back
= State
::StartDir
;
955 self.back
= State
::Prefix
;
956 if self.has_physical_root
{
957 self.path
= &self.path
[..self.path
.len() - 1];
958 return Some(Component
::RootDir
);
959 } else if let Some(p
) = self.prefix
{
960 if p
.has_implicit_root() && !p
.is_verbatim() {
961 return Some(Component
::RootDir
);
963 } else if self.include_cur_dir() {
964 self.path
= &self.path
[..self.path
.len() - 1];
965 return Some(Component
::CurDir
);
968 State
::Prefix
if self.prefix_len() > 0 => {
969 self.back
= State
::Done
;
970 return Some(Component
::Prefix(PrefixComponent
{
971 raw
: unsafe { OsStr::from_encoded_bytes_unchecked(self.path) }
,
972 parsed
: self.prefix
.unwrap(),
976 self.back
= State
::Done
;
979 State
::Done
=> unreachable
!(),
986 #[stable(feature = "fused", since = "1.26.0")]
987 impl FusedIterator
for Components
<'_
> {}
989 #[stable(feature = "rust1", since = "1.0.0")]
990 impl<'a
> PartialEq
for Components
<'a
> {
992 fn eq(&self, other
: &Components
<'a
>) -> bool
{
993 let Components { path: _, front: _, back: _, has_physical_root: _, prefix: _ }
= self;
995 // Fast path for exact matches, e.g. for hashmap lookups.
996 // Don't explicitly compare the prefix or has_physical_root fields since they'll
997 // either be covered by the `path` buffer or are only relevant for `prefix_verbatim()`.
998 if self.path
.len() == other
.path
.len()
999 && self.front
== other
.front
1000 && self.back
== State
::Body
1001 && other
.back
== State
::Body
1002 && self.prefix_verbatim() == other
.prefix_verbatim()
1004 // possible future improvement: this could bail out earlier if there were a
1005 // reverse memcmp/bcmp comparing back to front
1006 if self.path
== other
.path
{
1011 // compare back to front since absolute paths often share long prefixes
1012 Iterator
::eq(self.clone().rev(), other
.clone().rev())
1016 #[stable(feature = "rust1", since = "1.0.0")]
1017 impl Eq
for Components
<'_
> {}
1019 #[stable(feature = "rust1", since = "1.0.0")]
1020 impl<'a
> PartialOrd
for Components
<'a
> {
1022 fn partial_cmp(&self, other
: &Components
<'a
>) -> Option
<cmp
::Ordering
> {
1023 Some(compare_components(self.clone(), other
.clone()))
1027 #[stable(feature = "rust1", since = "1.0.0")]
1028 impl Ord
for Components
<'_
> {
1030 fn cmp(&self, other
: &Self) -> cmp
::Ordering
{
1031 compare_components(self.clone(), other
.clone())
1035 fn compare_components(mut left
: Components
<'_
>, mut right
: Components
<'_
>) -> cmp
::Ordering
{
1036 // Fast path for long shared prefixes
1038 // - compare raw bytes to find first mismatch
1039 // - backtrack to find separator before mismatch to avoid ambiguous parsings of '.' or '..' characters
1040 // - if found update state to only do a component-wise comparison on the remainder,
1041 // otherwise do it on the full path
1043 // The fast path isn't taken for paths with a PrefixComponent to avoid backtracking into
1044 // the middle of one
1045 if left
.prefix
.is_none() && right
.prefix
.is_none() && left
.front
== right
.front
{
1046 // possible future improvement: a [u8]::first_mismatch simd implementation
1047 let first_difference
= match left
.path
.iter().zip(right
.path
).position(|(&a
, &b
)| a
!= b
) {
1048 None
if left
.path
.len() == right
.path
.len() => return cmp
::Ordering
::Equal
,
1049 None
=> left
.path
.len().min(right
.path
.len()),
1053 if let Some(previous_sep
) =
1054 left
.path
[..first_difference
].iter().rposition(|&b
| left
.is_sep_byte(b
))
1056 let mismatched_component_start
= previous_sep
+ 1;
1057 left
.path
= &left
.path
[mismatched_component_start
..];
1058 left
.front
= State
::Body
;
1059 right
.path
= &right
.path
[mismatched_component_start
..];
1060 right
.front
= State
::Body
;
1064 Iterator
::cmp(left
, right
)
1067 /// An iterator over [`Path`] and its ancestors.
1069 /// This `struct` is created by the [`ancestors`] method on [`Path`].
1070 /// See its documentation for more.
1075 /// use std::path::Path;
1077 /// let path = Path::new("/foo/bar");
1079 /// for ancestor in path.ancestors() {
1080 /// println!("{}", ancestor.display());
1084 /// [`ancestors`]: Path::ancestors
1085 #[derive(Copy, Clone, Debug)]
1086 #[must_use = "iterators are lazy and do nothing unless consumed"]
1087 #[stable(feature = "path_ancestors", since = "1.28.0")]
1088 pub struct Ancestors
<'a
> {
1089 next
: Option
<&'a Path
>,
1092 #[stable(feature = "path_ancestors", since = "1.28.0")]
1093 impl<'a
> Iterator
for Ancestors
<'a
> {
1094 type Item
= &'a Path
;
1097 fn next(&mut self) -> Option
<Self::Item
> {
1098 let next
= self.next
;
1099 self.next
= next
.and_then(Path
::parent
);
1104 #[stable(feature = "path_ancestors", since = "1.28.0")]
1105 impl FusedIterator
for Ancestors
<'_
> {}
1107 ////////////////////////////////////////////////////////////////////////////////
1108 // Basic types and traits
1109 ////////////////////////////////////////////////////////////////////////////////
1111 /// An owned, mutable path (akin to [`String`]).
1113 /// This type provides methods like [`push`] and [`set_extension`] that mutate
1114 /// the path in place. It also implements [`Deref`] to [`Path`], meaning that
1115 /// all methods on [`Path`] slices are available on `PathBuf` values as well.
1117 /// [`push`]: PathBuf::push
1118 /// [`set_extension`]: PathBuf::set_extension
1120 /// More details about the overall approach can be found in
1121 /// the [module documentation](self).
1125 /// You can use [`push`] to build up a `PathBuf` from
1129 /// use std::path::PathBuf;
1131 /// let mut path = PathBuf::new();
1133 /// path.push(r"C:\");
1134 /// path.push("windows");
1135 /// path.push("system32");
1137 /// path.set_extension("dll");
1140 /// However, [`push`] is best used for dynamic situations. This is a better way
1141 /// to do this when you know all of the components ahead of time:
1144 /// use std::path::PathBuf;
1146 /// let path: PathBuf = [r"C:\", "windows", "system32.dll"].iter().collect();
1149 /// We can still do better than this! Since these are all strings, we can use
1153 /// use std::path::PathBuf;
1155 /// let path = PathBuf::from(r"C:\windows\system32.dll");
1158 /// Which method works best depends on what kind of situation you're in.
1159 #[cfg_attr(not(test), rustc_diagnostic_item = "PathBuf")]
1160 #[stable(feature = "rust1", since = "1.0.0")]
1161 // `PathBuf::as_mut_vec` current implementation relies
1162 // on `PathBuf` being layout-compatible with `Vec<u8>`.
1163 // However, `PathBuf` layout is considered an implementation detail and must not be relied upon. We
1164 // want `repr(transparent)` but we don't want it to show up in rustdoc, so we hide it under
1165 // `cfg(doc)`. This is an ad-hoc implementation of attribute privacy.
1166 #[cfg_attr(not(doc), repr(transparent))]
1167 pub struct PathBuf
{
1173 fn as_mut_vec(&mut self) -> &mut Vec
<u8> {
1174 unsafe { &mut *(self as *mut PathBuf as *mut Vec<u8>) }
1177 /// Allocates an empty `PathBuf`.
1182 /// use std::path::PathBuf;
1184 /// let path = PathBuf::new();
1186 #[stable(feature = "rust1", since = "1.0.0")]
1189 pub fn new() -> PathBuf
{
1190 PathBuf { inner: OsString::new() }
1193 /// Creates a new `PathBuf` with a given capacity used to create the
1194 /// internal [`OsString`]. See [`with_capacity`] defined on [`OsString`].
1199 /// use std::path::PathBuf;
1201 /// let mut path = PathBuf::with_capacity(10);
1202 /// let capacity = path.capacity();
1204 /// // This push is done without reallocating
1205 /// path.push(r"C:\");
1207 /// assert_eq!(capacity, path.capacity());
1210 /// [`with_capacity`]: OsString::with_capacity
1211 #[stable(feature = "path_buf_capacity", since = "1.44.0")]
1214 pub fn with_capacity(capacity
: usize) -> PathBuf
{
1215 PathBuf { inner: OsString::with_capacity(capacity) }
1218 /// Coerces to a [`Path`] slice.
1223 /// use std::path::{Path, PathBuf};
1225 /// let p = PathBuf::from("/test");
1226 /// assert_eq!(Path::new("/test"), p.as_path());
1228 #[stable(feature = "rust1", since = "1.0.0")]
1231 pub fn as_path(&self) -> &Path
{
1235 /// Extends `self` with `path`.
1237 /// If `path` is absolute, it replaces the current path.
1241 /// * if `path` has a root but no prefix (e.g., `\windows`), it
1242 /// replaces everything except for the prefix (if any) of `self`.
1243 /// * if `path` has a prefix but no root, it replaces `self`.
1244 /// * if `self` has a verbatim prefix (e.g. `\\?\C:\windows`)
1245 /// and `path` is not empty, the new path is normalized: all references
1246 /// to `.` and `..` are removed.
1248 /// Consider using [`Path::join`] if you need a new `PathBuf` instead of
1249 /// using this function on a cloned `PathBuf`.
1253 /// Pushing a relative path extends the existing path:
1256 /// use std::path::PathBuf;
1258 /// let mut path = PathBuf::from("/tmp");
1259 /// path.push("file.bk");
1260 /// assert_eq!(path, PathBuf::from("/tmp/file.bk"));
1263 /// Pushing an absolute path replaces the existing path:
1266 /// use std::path::PathBuf;
1268 /// let mut path = PathBuf::from("/tmp");
1269 /// path.push("/etc");
1270 /// assert_eq!(path, PathBuf::from("/etc"));
1272 #[stable(feature = "rust1", since = "1.0.0")]
1273 pub fn push
<P
: AsRef
<Path
>>(&mut self, path
: P
) {
1274 self._push(path
.as_ref())
1277 fn _push(&mut self, path
: &Path
) {
1278 // in general, a separator is needed if the rightmost byte is not a separator
1279 let mut need_sep
= self.as_mut_vec().last().map(|c
| !is_sep_byte(*c
)).unwrap_or(false);
1281 // in the special case of `C:` on Windows, do *not* add a separator
1282 let comps
= self.components();
1284 if comps
.prefix_len() > 0
1285 && comps
.prefix_len() == comps
.path
.len()
1286 && comps
.prefix
.unwrap().is_drive()
1291 // absolute `path` replaces `self`
1292 if path
.is_absolute() || path
.prefix().is_some() {
1293 self.as_mut_vec().truncate(0);
1295 // verbatim paths need . and .. removed
1296 } else if comps
.prefix_verbatim() && !path
.inner
.is_empty() {
1297 let mut buf
: Vec
<_
> = comps
.collect();
1298 for c
in path
.components() {
1300 Component
::RootDir
=> {
1304 Component
::CurDir
=> (),
1305 Component
::ParentDir
=> {
1306 if let Some(Component
::Normal(_
)) = buf
.last() {
1314 let mut res
= OsString
::new();
1315 let mut need_sep
= false;
1318 if need_sep
&& c
!= Component
::RootDir
{
1319 res
.push(MAIN_SEP_STR
);
1321 res
.push(c
.as_os_str());
1323 need_sep
= match c
{
1324 Component
::RootDir
=> false,
1325 Component
::Prefix(prefix
) => {
1326 !prefix
.parsed
.is_drive() && prefix
.parsed
.len() > 0
1335 // `path` has a root but no prefix, e.g., `\windows` (Windows only)
1336 } else if path
.has_root() {
1337 let prefix_len
= self.components().prefix_remaining();
1338 self.as_mut_vec().truncate(prefix_len
);
1340 // `path` is a pure relative path
1341 } else if need_sep
{
1342 self.inner
.push(MAIN_SEP_STR
);
1345 self.inner
.push(path
);
1348 /// Truncates `self` to [`self.parent`].
1350 /// Returns `false` and does nothing if [`self.parent`] is [`None`].
1351 /// Otherwise, returns `true`.
1353 /// [`self.parent`]: Path::parent
1358 /// use std::path::{Path, PathBuf};
1360 /// let mut p = PathBuf::from("/spirited/away.rs");
1363 /// assert_eq!(Path::new("/spirited"), p);
1365 /// assert_eq!(Path::new("/"), p);
1367 #[stable(feature = "rust1", since = "1.0.0")]
1368 pub fn pop(&mut self) -> bool
{
1369 match self.parent().map(|p
| p
.as_u8_slice().len()) {
1371 self.as_mut_vec().truncate(len
);
1378 /// Updates [`self.file_name`] to `file_name`.
1380 /// If [`self.file_name`] was [`None`], this is equivalent to pushing
1383 /// Otherwise it is equivalent to calling [`pop`] and then pushing
1384 /// `file_name`. The new path will be a sibling of the original path.
1385 /// (That is, it will have the same parent.)
1387 /// [`self.file_name`]: Path::file_name
1388 /// [`pop`]: PathBuf::pop
1393 /// use std::path::PathBuf;
1395 /// let mut buf = PathBuf::from("/");
1396 /// assert!(buf.file_name() == None);
1398 /// buf.set_file_name("foo.txt");
1399 /// assert!(buf == PathBuf::from("/foo.txt"));
1400 /// assert!(buf.file_name().is_some());
1402 /// buf.set_file_name("bar.txt");
1403 /// assert!(buf == PathBuf::from("/bar.txt"));
1405 /// buf.set_file_name("baz");
1406 /// assert!(buf == PathBuf::from("/baz"));
1408 #[stable(feature = "rust1", since = "1.0.0")]
1409 pub fn set_file_name
<S
: AsRef
<OsStr
>>(&mut self, file_name
: S
) {
1410 self._set_file_name(file_name
.as_ref())
1413 fn _set_file_name(&mut self, file_name
: &OsStr
) {
1414 if self.file_name().is_some() {
1415 let popped
= self.pop();
1416 debug_assert
!(popped
);
1418 self.push(file_name
);
1421 /// Updates [`self.extension`] to `Some(extension)` or to `None` if
1422 /// `extension` is empty.
1424 /// Returns `false` and does nothing if [`self.file_name`] is [`None`],
1425 /// returns `true` and updates the extension otherwise.
1427 /// If [`self.extension`] is [`None`], the extension is added; otherwise
1430 /// If `extension` is the empty string, [`self.extension`] will be [`None`]
1431 /// afterwards, not `Some("")`.
1435 /// The new `extension` may contain dots and will be used in its entirety,
1436 /// but only the part after the final dot will be reflected in
1437 /// [`self.extension`].
1439 /// If the file stem contains internal dots and `extension` is empty, part
1440 /// of the old file stem will be considered the new [`self.extension`].
1442 /// See the examples below.
1444 /// [`self.file_name`]: Path::file_name
1445 /// [`self.extension`]: Path::extension
1450 /// use std::path::{Path, PathBuf};
1452 /// let mut p = PathBuf::from("/feel/the");
1454 /// p.set_extension("force");
1455 /// assert_eq!(Path::new("/feel/the.force"), p.as_path());
1457 /// p.set_extension("dark.side");
1458 /// assert_eq!(Path::new("/feel/the.dark.side"), p.as_path());
1460 /// p.set_extension("cookie");
1461 /// assert_eq!(Path::new("/feel/the.dark.cookie"), p.as_path());
1463 /// p.set_extension("");
1464 /// assert_eq!(Path::new("/feel/the.dark"), p.as_path());
1466 /// p.set_extension("");
1467 /// assert_eq!(Path::new("/feel/the"), p.as_path());
1469 /// p.set_extension("");
1470 /// assert_eq!(Path::new("/feel/the"), p.as_path());
1472 #[stable(feature = "rust1", since = "1.0.0")]
1473 pub fn set_extension
<S
: AsRef
<OsStr
>>(&mut self, extension
: S
) -> bool
{
1474 self._set_extension(extension
.as_ref())
1477 fn _set_extension(&mut self, extension
: &OsStr
) -> bool
{
1478 let file_stem
= match self.file_stem() {
1479 None
=> return false,
1480 Some(f
) => f
.as_encoded_bytes(),
1483 // truncate until right after the file stem
1484 let end_file_stem
= file_stem
[file_stem
.len()..].as_ptr().addr();
1485 let start
= self.inner
.as_encoded_bytes().as_ptr().addr();
1486 let v
= self.as_mut_vec();
1487 v
.truncate(end_file_stem
.wrapping_sub(start
));
1489 // add the new extension, if any
1490 let new
= extension
.as_encoded_bytes();
1491 if !new
.is_empty() {
1492 v
.reserve_exact(new
.len() + 1);
1494 v
.extend_from_slice(new
);
1500 /// Yields a mutable reference to the underlying [`OsString`] instance.
1505 /// use std::path::{Path, PathBuf};
1507 /// let mut path = PathBuf::from("/foo");
1509 /// path.push("bar");
1510 /// assert_eq!(path, Path::new("/foo/bar"));
1512 /// // OsString's `push` does not add a separator.
1513 /// path.as_mut_os_string().push("baz");
1514 /// assert_eq!(path, Path::new("/foo/barbaz"));
1516 #[stable(feature = "path_as_mut_os_str", since = "1.70.0")]
1519 pub fn as_mut_os_string(&mut self) -> &mut OsString
{
1523 /// Consumes the `PathBuf`, yielding its internal [`OsString`] storage.
1528 /// use std::path::PathBuf;
1530 /// let p = PathBuf::from("/the/head");
1531 /// let os_str = p.into_os_string();
1533 #[stable(feature = "rust1", since = "1.0.0")]
1534 #[must_use = "`self` will be dropped if the result is not used"]
1536 pub fn into_os_string(self) -> OsString
{
1540 /// Converts this `PathBuf` into a [boxed](Box) [`Path`].
1541 #[stable(feature = "into_boxed_path", since = "1.20.0")]
1542 #[must_use = "`self` will be dropped if the result is not used"]
1544 pub fn into_boxed_path(self) -> Box
<Path
> {
1545 let rw
= Box
::into_raw(self.inner
.into_boxed_os_str()) as *mut Path
;
1546 unsafe { Box::from_raw(rw) }
1549 /// Invokes [`capacity`] on the underlying instance of [`OsString`].
1551 /// [`capacity`]: OsString::capacity
1552 #[stable(feature = "path_buf_capacity", since = "1.44.0")]
1555 pub fn capacity(&self) -> usize {
1556 self.inner
.capacity()
1559 /// Invokes [`clear`] on the underlying instance of [`OsString`].
1561 /// [`clear`]: OsString::clear
1562 #[stable(feature = "path_buf_capacity", since = "1.44.0")]
1564 pub fn clear(&mut self) {
1568 /// Invokes [`reserve`] on the underlying instance of [`OsString`].
1570 /// [`reserve`]: OsString::reserve
1571 #[stable(feature = "path_buf_capacity", since = "1.44.0")]
1573 pub fn reserve(&mut self, additional
: usize) {
1574 self.inner
.reserve(additional
)
1577 /// Invokes [`try_reserve`] on the underlying instance of [`OsString`].
1579 /// [`try_reserve`]: OsString::try_reserve
1580 #[stable(feature = "try_reserve_2", since = "1.63.0")]
1582 pub fn try_reserve(&mut self, additional
: usize) -> Result
<(), TryReserveError
> {
1583 self.inner
.try_reserve(additional
)
1586 /// Invokes [`reserve_exact`] on the underlying instance of [`OsString`].
1588 /// [`reserve_exact`]: OsString::reserve_exact
1589 #[stable(feature = "path_buf_capacity", since = "1.44.0")]
1591 pub fn reserve_exact(&mut self, additional
: usize) {
1592 self.inner
.reserve_exact(additional
)
1595 /// Invokes [`try_reserve_exact`] on the underlying instance of [`OsString`].
1597 /// [`try_reserve_exact`]: OsString::try_reserve_exact
1598 #[stable(feature = "try_reserve_2", since = "1.63.0")]
1600 pub fn try_reserve_exact(&mut self, additional
: usize) -> Result
<(), TryReserveError
> {
1601 self.inner
.try_reserve_exact(additional
)
1604 /// Invokes [`shrink_to_fit`] on the underlying instance of [`OsString`].
1606 /// [`shrink_to_fit`]: OsString::shrink_to_fit
1607 #[stable(feature = "path_buf_capacity", since = "1.44.0")]
1609 pub fn shrink_to_fit(&mut self) {
1610 self.inner
.shrink_to_fit()
1613 /// Invokes [`shrink_to`] on the underlying instance of [`OsString`].
1615 /// [`shrink_to`]: OsString::shrink_to
1616 #[stable(feature = "shrink_to", since = "1.56.0")]
1618 pub fn shrink_to(&mut self, min_capacity
: usize) {
1619 self.inner
.shrink_to(min_capacity
)
1623 #[stable(feature = "rust1", since = "1.0.0")]
1624 impl Clone
for PathBuf
{
1626 fn clone(&self) -> Self {
1627 PathBuf { inner: self.inner.clone() }
1631 fn clone_from(&mut self, source
: &Self) {
1632 self.inner
.clone_from(&source
.inner
)
1636 #[stable(feature = "box_from_path", since = "1.17.0")]
1637 impl From
<&Path
> for Box
<Path
> {
1638 /// Creates a boxed [`Path`] from a reference.
1640 /// This will allocate and clone `path` to it.
1641 fn from(path
: &Path
) -> Box
<Path
> {
1642 let boxed
: Box
<OsStr
> = path
.inner
.into();
1643 let rw
= Box
::into_raw(boxed
) as *mut Path
;
1644 unsafe { Box::from_raw(rw) }
1648 #[stable(feature = "box_from_cow", since = "1.45.0")]
1649 impl From
<Cow
<'_
, Path
>> for Box
<Path
> {
1650 /// Creates a boxed [`Path`] from a clone-on-write pointer.
1652 /// Converting from a `Cow::Owned` does not clone or allocate.
1654 fn from(cow
: Cow
<'_
, Path
>) -> Box
<Path
> {
1656 Cow
::Borrowed(path
) => Box
::from(path
),
1657 Cow
::Owned(path
) => Box
::from(path
),
1662 #[stable(feature = "path_buf_from_box", since = "1.18.0")]
1663 impl From
<Box
<Path
>> for PathBuf
{
1664 /// Converts a <code>[Box]<[Path]></code> into a [`PathBuf`].
1666 /// This conversion does not allocate or copy memory.
1668 fn from(boxed
: Box
<Path
>) -> PathBuf
{
1669 boxed
.into_path_buf()
1673 #[stable(feature = "box_from_path_buf", since = "1.20.0")]
1674 impl From
<PathBuf
> for Box
<Path
> {
1675 /// Converts a [`PathBuf`] into a <code>[Box]<[Path]></code>.
1677 /// This conversion currently should not allocate memory,
1678 /// but this behavior is not guaranteed on all platforms or in all future versions.
1680 fn from(p
: PathBuf
) -> Box
<Path
> {
1685 #[stable(feature = "more_box_slice_clone", since = "1.29.0")]
1686 impl Clone
for Box
<Path
> {
1688 fn clone(&self) -> Self {
1689 self.to_path_buf().into_boxed_path()
1693 #[stable(feature = "rust1", since = "1.0.0")]
1694 impl<T
: ?Sized
+ AsRef
<OsStr
>> From
<&T
> for PathBuf
{
1695 /// Converts a borrowed [`OsStr`] to a [`PathBuf`].
1697 /// Allocates a [`PathBuf`] and copies the data into it.
1699 fn from(s
: &T
) -> PathBuf
{
1700 PathBuf
::from(s
.as_ref().to_os_string())
1704 #[stable(feature = "rust1", since = "1.0.0")]
1705 impl From
<OsString
> for PathBuf
{
1706 /// Converts an [`OsString`] into a [`PathBuf`]
1708 /// This conversion does not allocate or copy memory.
1710 fn from(s
: OsString
) -> PathBuf
{
1711 PathBuf { inner: s }
1715 #[stable(feature = "from_path_buf_for_os_string", since = "1.14.0")]
1716 impl From
<PathBuf
> for OsString
{
1717 /// Converts a [`PathBuf`] into an [`OsString`]
1719 /// This conversion does not allocate or copy memory.
1721 fn from(path_buf
: PathBuf
) -> OsString
{
1726 #[stable(feature = "rust1", since = "1.0.0")]
1727 impl From
<String
> for PathBuf
{
1728 /// Converts a [`String`] into a [`PathBuf`]
1730 /// This conversion does not allocate or copy memory.
1732 fn from(s
: String
) -> PathBuf
{
1733 PathBuf
::from(OsString
::from(s
))
1737 #[stable(feature = "path_from_str", since = "1.32.0")]
1738 impl FromStr
for PathBuf
{
1739 type Err
= core
::convert
::Infallible
;
1742 fn from_str(s
: &str) -> Result
<Self, Self::Err
> {
1743 Ok(PathBuf
::from(s
))
1747 #[stable(feature = "rust1", since = "1.0.0")]
1748 impl<P
: AsRef
<Path
>> FromIterator
<P
> for PathBuf
{
1749 fn from_iter
<I
: IntoIterator
<Item
= P
>>(iter
: I
) -> PathBuf
{
1750 let mut buf
= PathBuf
::new();
1756 #[stable(feature = "rust1", since = "1.0.0")]
1757 impl<P
: AsRef
<Path
>> Extend
<P
> for PathBuf
{
1758 fn extend
<I
: IntoIterator
<Item
= P
>>(&mut self, iter
: I
) {
1759 iter
.into_iter().for_each(move |p
| self.push(p
.as_ref()));
1763 fn extend_one(&mut self, p
: P
) {
1764 self.push(p
.as_ref());
1768 #[stable(feature = "rust1", since = "1.0.0")]
1769 impl fmt
::Debug
for PathBuf
{
1770 fn fmt(&self, formatter
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
1771 fmt
::Debug
::fmt(&**self, formatter
)
1775 #[stable(feature = "rust1", since = "1.0.0")]
1776 impl ops
::Deref
for PathBuf
{
1779 fn deref(&self) -> &Path
{
1780 Path
::new(&self.inner
)
1784 #[stable(feature = "path_buf_deref_mut", since = "1.68.0")]
1785 impl ops
::DerefMut
for PathBuf
{
1787 fn deref_mut(&mut self) -> &mut Path
{
1788 Path
::from_inner_mut(&mut self.inner
)
1792 #[stable(feature = "rust1", since = "1.0.0")]
1793 impl Borrow
<Path
> for PathBuf
{
1795 fn borrow(&self) -> &Path
{
1800 #[stable(feature = "default_for_pathbuf", since = "1.17.0")]
1801 impl Default
for PathBuf
{
1803 fn default() -> Self {
1808 #[stable(feature = "cow_from_path", since = "1.6.0")]
1809 impl<'a
> From
<&'a Path
> for Cow
<'a
, Path
> {
1810 /// Creates a clone-on-write pointer from a reference to
1813 /// This conversion does not clone or allocate.
1815 fn from(s
: &'a Path
) -> Cow
<'a
, Path
> {
1820 #[stable(feature = "cow_from_path", since = "1.6.0")]
1821 impl<'a
> From
<PathBuf
> for Cow
<'a
, Path
> {
1822 /// Creates a clone-on-write pointer from an owned
1823 /// instance of [`PathBuf`].
1825 /// This conversion does not clone or allocate.
1827 fn from(s
: PathBuf
) -> Cow
<'a
, Path
> {
1832 #[stable(feature = "cow_from_pathbuf_ref", since = "1.28.0")]
1833 impl<'a
> From
<&'a PathBuf
> for Cow
<'a
, Path
> {
1834 /// Creates a clone-on-write pointer from a reference to
1837 /// This conversion does not clone or allocate.
1839 fn from(p
: &'a PathBuf
) -> Cow
<'a
, Path
> {
1840 Cow
::Borrowed(p
.as_path())
1844 #[stable(feature = "pathbuf_from_cow_path", since = "1.28.0")]
1845 impl<'a
> From
<Cow
<'a
, Path
>> for PathBuf
{
1846 /// Converts a clone-on-write pointer to an owned path.
1848 /// Converting from a `Cow::Owned` does not clone or allocate.
1850 fn from(p
: Cow
<'a
, Path
>) -> Self {
1855 #[stable(feature = "shared_from_slice2", since = "1.24.0")]
1856 impl From
<PathBuf
> for Arc
<Path
> {
1857 /// Converts a [`PathBuf`] into an <code>[Arc]<[Path]></code> by moving the [`PathBuf`] data
1858 /// into a new [`Arc`] buffer.
1860 fn from(s
: PathBuf
) -> Arc
<Path
> {
1861 let arc
: Arc
<OsStr
> = Arc
::from(s
.into_os_string());
1862 unsafe { Arc::from_raw(Arc::into_raw(arc) as *const Path) }
1866 #[stable(feature = "shared_from_slice2", since = "1.24.0")]
1867 impl From
<&Path
> for Arc
<Path
> {
1868 /// Converts a [`Path`] into an [`Arc`] by copying the [`Path`] data into a new [`Arc`] buffer.
1870 fn from(s
: &Path
) -> Arc
<Path
> {
1871 let arc
: Arc
<OsStr
> = Arc
::from(s
.as_os_str());
1872 unsafe { Arc::from_raw(Arc::into_raw(arc) as *const Path) }
1876 #[stable(feature = "shared_from_slice2", since = "1.24.0")]
1877 impl From
<PathBuf
> for Rc
<Path
> {
1878 /// Converts a [`PathBuf`] into an <code>[Rc]<[Path]></code> by moving the [`PathBuf`] data into
1879 /// a new [`Rc`] buffer.
1881 fn from(s
: PathBuf
) -> Rc
<Path
> {
1882 let rc
: Rc
<OsStr
> = Rc
::from(s
.into_os_string());
1883 unsafe { Rc::from_raw(Rc::into_raw(rc) as *const Path) }
1887 #[stable(feature = "shared_from_slice2", since = "1.24.0")]
1888 impl From
<&Path
> for Rc
<Path
> {
1889 /// Converts a [`Path`] into an [`Rc`] by copying the [`Path`] data into a new [`Rc`] buffer.
1891 fn from(s
: &Path
) -> Rc
<Path
> {
1892 let rc
: Rc
<OsStr
> = Rc
::from(s
.as_os_str());
1893 unsafe { Rc::from_raw(Rc::into_raw(rc) as *const Path) }
1897 #[stable(feature = "rust1", since = "1.0.0")]
1898 impl ToOwned
for Path
{
1899 type Owned
= PathBuf
;
1901 fn to_owned(&self) -> PathBuf
{
1905 fn clone_into(&self, target
: &mut PathBuf
) {
1906 self.inner
.clone_into(&mut target
.inner
);
1910 #[stable(feature = "rust1", since = "1.0.0")]
1911 impl PartialEq
for PathBuf
{
1913 fn eq(&self, other
: &PathBuf
) -> bool
{
1914 self.components() == other
.components()
1918 #[stable(feature = "rust1", since = "1.0.0")]
1919 impl Hash
for PathBuf
{
1920 fn hash
<H
: Hasher
>(&self, h
: &mut H
) {
1921 self.as_path().hash(h
)
1925 #[stable(feature = "rust1", since = "1.0.0")]
1926 impl Eq
for PathBuf {}
1928 #[stable(feature = "rust1", since = "1.0.0")]
1929 impl PartialOrd
for PathBuf
{
1931 fn partial_cmp(&self, other
: &PathBuf
) -> Option
<cmp
::Ordering
> {
1932 Some(compare_components(self.components(), other
.components()))
1936 #[stable(feature = "rust1", since = "1.0.0")]
1937 impl Ord
for PathBuf
{
1939 fn cmp(&self, other
: &PathBuf
) -> cmp
::Ordering
{
1940 compare_components(self.components(), other
.components())
1944 #[stable(feature = "rust1", since = "1.0.0")]
1945 impl AsRef
<OsStr
> for PathBuf
{
1947 fn as_ref(&self) -> &OsStr
{
1952 /// A slice of a path (akin to [`str`]).
1954 /// This type supports a number of operations for inspecting a path, including
1955 /// breaking the path into its components (separated by `/` on Unix and by either
1956 /// `/` or `\` on Windows), extracting the file name, determining whether the path
1957 /// is absolute, and so on.
1959 /// This is an *unsized* type, meaning that it must always be used behind a
1960 /// pointer like `&` or [`Box`]. For an owned version of this type,
1961 /// see [`PathBuf`].
1963 /// More details about the overall approach can be found in
1964 /// the [module documentation](self).
1969 /// use std::path::Path;
1970 /// use std::ffi::OsStr;
1972 /// // Note: this example does work on Windows
1973 /// let path = Path::new("./foo/bar.txt");
1975 /// let parent = path.parent();
1976 /// assert_eq!(parent, Some(Path::new("./foo")));
1978 /// let file_stem = path.file_stem();
1979 /// assert_eq!(file_stem, Some(OsStr::new("bar")));
1981 /// let extension = path.extension();
1982 /// assert_eq!(extension, Some(OsStr::new("txt")));
1984 #[cfg_attr(not(test), rustc_diagnostic_item = "Path")]
1985 #[stable(feature = "rust1", since = "1.0.0")]
1986 // `Path::new` current implementation relies
1987 // on `Path` being layout-compatible with `OsStr`.
1988 // However, `Path` layout is considered an implementation detail and must not be relied upon. We
1989 // want `repr(transparent)` but we don't want it to show up in rustdoc, so we hide it under
1990 // `cfg(doc)`. This is an ad-hoc implementation of attribute privacy.
1991 #[cfg_attr(not(doc), repr(transparent))]
1996 /// An error returned from [`Path::strip_prefix`] if the prefix was not found.
1998 /// This `struct` is created by the [`strip_prefix`] method on [`Path`].
1999 /// See its documentation for more.
2001 /// [`strip_prefix`]: Path::strip_prefix
2002 #[derive(Debug, Clone, PartialEq, Eq)]
2003 #[stable(since = "1.7.0", feature = "strip_prefix")]
2004 pub struct StripPrefixError(());
2007 // The following (private!) function allows construction of a path from a u8
2008 // slice, which is only safe when it is known to follow the OsStr encoding.
2009 unsafe fn from_u8_slice(s
: &[u8]) -> &Path
{
2010 unsafe { Path::new(OsStr::from_encoded_bytes_unchecked(s)) }
2012 // The following (private!) function reveals the byte encoding used for OsStr.
2013 fn as_u8_slice(&self) -> &[u8] {
2014 self.inner
.as_encoded_bytes()
2017 /// Directly wraps a string slice as a `Path` slice.
2019 /// This is a cost-free conversion.
2024 /// use std::path::Path;
2026 /// Path::new("foo.txt");
2029 /// You can create `Path`s from `String`s, or even other `Path`s:
2032 /// use std::path::Path;
2034 /// let string = String::from("foo.txt");
2035 /// let from_string = Path::new(&string);
2036 /// let from_path = Path::new(&from_string);
2037 /// assert_eq!(from_string, from_path);
2039 #[stable(feature = "rust1", since = "1.0.0")]
2040 pub fn new
<S
: AsRef
<OsStr
> + ?Sized
>(s
: &S
) -> &Path
{
2041 unsafe { &*(s.as_ref() as *const OsStr as *const Path) }
2044 fn from_inner_mut(inner
: &mut OsStr
) -> &mut Path
{
2045 // SAFETY: Path is just a wrapper around OsStr,
2046 // therefore converting &mut OsStr to &mut Path is safe.
2047 unsafe { &mut *(inner as *mut OsStr as *mut Path) }
2050 /// Yields the underlying [`OsStr`] slice.
2055 /// use std::path::Path;
2057 /// let os_str = Path::new("foo.txt").as_os_str();
2058 /// assert_eq!(os_str, std::ffi::OsStr::new("foo.txt"));
2060 #[stable(feature = "rust1", since = "1.0.0")]
2063 pub fn as_os_str(&self) -> &OsStr
{
2067 /// Yields a mutable reference to the underlying [`OsStr`] slice.
2072 /// use std::path::{Path, PathBuf};
2074 /// let mut path = PathBuf::from("Foo.TXT");
2076 /// assert_ne!(path, Path::new("foo.txt"));
2078 /// path.as_mut_os_str().make_ascii_lowercase();
2079 /// assert_eq!(path, Path::new("foo.txt"));
2081 #[stable(feature = "path_as_mut_os_str", since = "1.70.0")]
2084 pub fn as_mut_os_str(&mut self) -> &mut OsStr
{
2088 /// Yields a [`&str`] slice if the `Path` is valid unicode.
2090 /// This conversion may entail doing a check for UTF-8 validity.
2091 /// Note that validation is performed because non-UTF-8 strings are
2092 /// perfectly valid for some OS.
2099 /// use std::path::Path;
2101 /// let path = Path::new("foo.txt");
2102 /// assert_eq!(path.to_str(), Some("foo.txt"));
2104 #[stable(feature = "rust1", since = "1.0.0")]
2105 #[must_use = "this returns the result of the operation, \
2106 without modifying the original"]
2108 pub fn to_str(&self) -> Option
<&str> {
2112 /// Converts a `Path` to a [`Cow<str>`].
2114 /// Any non-Unicode sequences are replaced with
2115 /// [`U+FFFD REPLACEMENT CHARACTER`][U+FFFD].
2117 /// [U+FFFD]: super::char::REPLACEMENT_CHARACTER
2121 /// Calling `to_string_lossy` on a `Path` with valid unicode:
2124 /// use std::path::Path;
2126 /// let path = Path::new("foo.txt");
2127 /// assert_eq!(path.to_string_lossy(), "foo.txt");
2130 /// Had `path` contained invalid unicode, the `to_string_lossy` call might
2131 /// have returned `"fo�.txt"`.
2132 #[stable(feature = "rust1", since = "1.0.0")]
2133 #[must_use = "this returns the result of the operation, \
2134 without modifying the original"]
2136 pub fn to_string_lossy(&self) -> Cow
<'_
, str> {
2137 self.inner
.to_string_lossy()
2140 /// Converts a `Path` to an owned [`PathBuf`].
2145 /// use std::path::Path;
2147 /// let path_buf = Path::new("foo.txt").to_path_buf();
2148 /// assert_eq!(path_buf, std::path::PathBuf::from("foo.txt"));
2150 #[rustc_conversion_suggestion]
2151 #[must_use = "this returns the result of the operation, \
2152 without modifying the original"]
2153 #[stable(feature = "rust1", since = "1.0.0")]
2154 pub fn to_path_buf(&self) -> PathBuf
{
2155 PathBuf
::from(self.inner
.to_os_string())
2158 /// Returns `true` if the `Path` is absolute, i.e., if it is independent of
2159 /// the current directory.
2161 /// * On Unix, a path is absolute if it starts with the root, so
2162 /// `is_absolute` and [`has_root`] are equivalent.
2164 /// * On Windows, a path is absolute if it has a prefix and starts with the
2165 /// root: `c:\windows` is absolute, while `c:temp` and `\temp` are not.
2170 /// use std::path::Path;
2172 /// assert!(!Path::new("foo.txt").is_absolute());
2175 /// [`has_root`]: Path::has_root
2176 #[stable(feature = "rust1", since = "1.0.0")]
2178 #[allow(deprecated)]
2179 pub fn is_absolute(&self) -> bool
{
2180 if cfg
!(target_os
= "redox") {
2181 // FIXME: Allow Redox prefixes
2182 self.has_root() || has_redox_scheme(self.as_u8_slice())
2184 self.has_root() && (cfg
!(any(unix
, target_os
= "wasi")) || self.prefix().is_some())
2188 /// Returns `true` if the `Path` is relative, i.e., not absolute.
2190 /// See [`is_absolute`]'s documentation for more details.
2195 /// use std::path::Path;
2197 /// assert!(Path::new("foo.txt").is_relative());
2200 /// [`is_absolute`]: Path::is_absolute
2201 #[stable(feature = "rust1", since = "1.0.0")]
2204 pub fn is_relative(&self) -> bool
{
2208 fn prefix(&self) -> Option
<Prefix
<'_
>> {
2209 self.components().prefix
2212 /// Returns `true` if the `Path` has a root.
2214 /// * On Unix, a path has a root if it begins with `/`.
2216 /// * On Windows, a path has a root if it:
2217 /// * has no prefix and begins with a separator, e.g., `\windows`
2218 /// * has a prefix followed by a separator, e.g., `c:\windows` but not `c:windows`
2219 /// * has any non-disk prefix, e.g., `\\server\share`
2224 /// use std::path::Path;
2226 /// assert!(Path::new("/etc/passwd").has_root());
2228 #[stable(feature = "rust1", since = "1.0.0")]
2231 pub fn has_root(&self) -> bool
{
2232 self.components().has_root()
2235 /// Returns the `Path` without its final component, if there is one.
2237 /// This means it returns `Some("")` for relative paths with one component.
2239 /// Returns [`None`] if the path terminates in a root or prefix, or if it's
2240 /// the empty string.
2245 /// use std::path::Path;
2247 /// let path = Path::new("/foo/bar");
2248 /// let parent = path.parent().unwrap();
2249 /// assert_eq!(parent, Path::new("/foo"));
2251 /// let grand_parent = parent.parent().unwrap();
2252 /// assert_eq!(grand_parent, Path::new("/"));
2253 /// assert_eq!(grand_parent.parent(), None);
2255 /// let relative_path = Path::new("foo/bar");
2256 /// let parent = relative_path.parent();
2257 /// assert_eq!(parent, Some(Path::new("foo")));
2258 /// let grand_parent = parent.and_then(Path::parent);
2259 /// assert_eq!(grand_parent, Some(Path::new("")));
2260 /// let great_grand_parent = grand_parent.and_then(Path::parent);
2261 /// assert_eq!(great_grand_parent, None);
2263 #[stable(feature = "rust1", since = "1.0.0")]
2264 #[doc(alias = "dirname")]
2266 pub fn parent(&self) -> Option
<&Path
> {
2267 let mut comps
= self.components();
2268 let comp
= comps
.next_back();
2269 comp
.and_then(|p
| match p
{
2270 Component
::Normal(_
) | Component
::CurDir
| Component
::ParentDir
=> {
2271 Some(comps
.as_path())
2277 /// Produces an iterator over `Path` and its ancestors.
2279 /// The iterator will yield the `Path` that is returned if the [`parent`] method is used zero
2280 /// or more times. That means, the iterator will yield `&self`, `&self.parent().unwrap()`,
2281 /// `&self.parent().unwrap().parent().unwrap()` and so on. If the [`parent`] method returns
2282 /// [`None`], the iterator will do likewise. The iterator will always yield at least one value,
2288 /// use std::path::Path;
2290 /// let mut ancestors = Path::new("/foo/bar").ancestors();
2291 /// assert_eq!(ancestors.next(), Some(Path::new("/foo/bar")));
2292 /// assert_eq!(ancestors.next(), Some(Path::new("/foo")));
2293 /// assert_eq!(ancestors.next(), Some(Path::new("/")));
2294 /// assert_eq!(ancestors.next(), None);
2296 /// let mut ancestors = Path::new("../foo/bar").ancestors();
2297 /// assert_eq!(ancestors.next(), Some(Path::new("../foo/bar")));
2298 /// assert_eq!(ancestors.next(), Some(Path::new("../foo")));
2299 /// assert_eq!(ancestors.next(), Some(Path::new("..")));
2300 /// assert_eq!(ancestors.next(), Some(Path::new("")));
2301 /// assert_eq!(ancestors.next(), None);
2304 /// [`parent`]: Path::parent
2305 #[stable(feature = "path_ancestors", since = "1.28.0")]
2307 pub fn ancestors(&self) -> Ancestors
<'_
> {
2308 Ancestors { next: Some(&self) }
2311 /// Returns the final component of the `Path`, if there is one.
2313 /// If the path is a normal file, this is the file name. If it's the path of a directory, this
2314 /// is the directory name.
2316 /// Returns [`None`] if the path terminates in `..`.
2321 /// use std::path::Path;
2322 /// use std::ffi::OsStr;
2324 /// assert_eq!(Some(OsStr::new("bin")), Path::new("/usr/bin/").file_name());
2325 /// assert_eq!(Some(OsStr::new("foo.txt")), Path::new("tmp/foo.txt").file_name());
2326 /// assert_eq!(Some(OsStr::new("foo.txt")), Path::new("foo.txt/.").file_name());
2327 /// assert_eq!(Some(OsStr::new("foo.txt")), Path::new("foo.txt/.//").file_name());
2328 /// assert_eq!(None, Path::new("foo.txt/..").file_name());
2329 /// assert_eq!(None, Path::new("/").file_name());
2331 #[stable(feature = "rust1", since = "1.0.0")]
2332 #[doc(alias = "basename")]
2334 pub fn file_name(&self) -> Option
<&OsStr
> {
2335 self.components().next_back().and_then(|p
| match p
{
2336 Component
::Normal(p
) => Some(p
),
2341 /// Returns a path that, when joined onto `base`, yields `self`.
2345 /// If `base` is not a prefix of `self` (i.e., [`starts_with`]
2346 /// returns `false`), returns [`Err`].
2348 /// [`starts_with`]: Path::starts_with
2353 /// use std::path::{Path, PathBuf};
2355 /// let path = Path::new("/test/haha/foo.txt");
2357 /// assert_eq!(path.strip_prefix("/"), Ok(Path::new("test/haha/foo.txt")));
2358 /// assert_eq!(path.strip_prefix("/test"), Ok(Path::new("haha/foo.txt")));
2359 /// assert_eq!(path.strip_prefix("/test/"), Ok(Path::new("haha/foo.txt")));
2360 /// assert_eq!(path.strip_prefix("/test/haha/foo.txt"), Ok(Path::new("")));
2361 /// assert_eq!(path.strip_prefix("/test/haha/foo.txt/"), Ok(Path::new("")));
2363 /// assert!(path.strip_prefix("test").is_err());
2364 /// assert!(path.strip_prefix("/haha").is_err());
2366 /// let prefix = PathBuf::from("/test/");
2367 /// assert_eq!(path.strip_prefix(prefix), Ok(Path::new("haha/foo.txt")));
2369 #[stable(since = "1.7.0", feature = "path_strip_prefix")]
2370 pub fn strip_prefix
<P
>(&self, base
: P
) -> Result
<&Path
, StripPrefixError
>
2374 self._strip_prefix(base
.as_ref())
2377 fn _strip_prefix(&self, base
: &Path
) -> Result
<&Path
, StripPrefixError
> {
2378 iter_after(self.components(), base
.components())
2379 .map(|c
| c
.as_path())
2380 .ok_or(StripPrefixError(()))
2383 /// Determines whether `base` is a prefix of `self`.
2385 /// Only considers whole path components to match.
2390 /// use std::path::Path;
2392 /// let path = Path::new("/etc/passwd");
2394 /// assert!(path.starts_with("/etc"));
2395 /// assert!(path.starts_with("/etc/"));
2396 /// assert!(path.starts_with("/etc/passwd"));
2397 /// assert!(path.starts_with("/etc/passwd/")); // extra slash is okay
2398 /// assert!(path.starts_with("/etc/passwd///")); // multiple extra slashes are okay
2400 /// assert!(!path.starts_with("/e"));
2401 /// assert!(!path.starts_with("/etc/passwd.txt"));
2403 /// assert!(!Path::new("/etc/foo.rs").starts_with("/etc/foo"));
2405 #[stable(feature = "rust1", since = "1.0.0")]
2407 pub fn starts_with
<P
: AsRef
<Path
>>(&self, base
: P
) -> bool
{
2408 self._starts_with(base
.as_ref())
2411 fn _starts_with(&self, base
: &Path
) -> bool
{
2412 iter_after(self.components(), base
.components()).is_some()
2415 /// Determines whether `child` is a suffix of `self`.
2417 /// Only considers whole path components to match.
2422 /// use std::path::Path;
2424 /// let path = Path::new("/etc/resolv.conf");
2426 /// assert!(path.ends_with("resolv.conf"));
2427 /// assert!(path.ends_with("etc/resolv.conf"));
2428 /// assert!(path.ends_with("/etc/resolv.conf"));
2430 /// assert!(!path.ends_with("/resolv.conf"));
2431 /// assert!(!path.ends_with("conf")); // use .extension() instead
2433 #[stable(feature = "rust1", since = "1.0.0")]
2435 pub fn ends_with
<P
: AsRef
<Path
>>(&self, child
: P
) -> bool
{
2436 self._ends_with(child
.as_ref())
2439 fn _ends_with(&self, child
: &Path
) -> bool
{
2440 iter_after(self.components().rev(), child
.components().rev()).is_some()
2443 /// Extracts the stem (non-extension) portion of [`self.file_name`].
2445 /// [`self.file_name`]: Path::file_name
2449 /// * [`None`], if there is no file name;
2450 /// * The entire file name if there is no embedded `.`;
2451 /// * The entire file name if the file name begins with `.` and has no other `.`s within;
2452 /// * Otherwise, the portion of the file name before the final `.`
2457 /// use std::path::Path;
2459 /// assert_eq!("foo", Path::new("foo.rs").file_stem().unwrap());
2460 /// assert_eq!("foo.tar", Path::new("foo.tar.gz").file_stem().unwrap());
2464 /// This method is similar to [`Path::file_prefix`], which extracts the portion of the file name
2465 /// before the *first* `.`
2467 /// [`Path::file_prefix`]: Path::file_prefix
2469 #[stable(feature = "rust1", since = "1.0.0")]
2471 pub fn file_stem(&self) -> Option
<&OsStr
> {
2472 self.file_name().map(rsplit_file_at_dot
).and_then(|(before
, after
)| before
.or(after
))
2475 /// Extracts the prefix of [`self.file_name`].
2479 /// * [`None`], if there is no file name;
2480 /// * The entire file name if there is no embedded `.`;
2481 /// * The portion of the file name before the first non-beginning `.`;
2482 /// * The entire file name if the file name begins with `.` and has no other `.`s within;
2483 /// * The portion of the file name before the second `.` if the file name begins with `.`
2485 /// [`self.file_name`]: Path::file_name
2490 /// # #![feature(path_file_prefix)]
2491 /// use std::path::Path;
2493 /// assert_eq!("foo", Path::new("foo.rs").file_prefix().unwrap());
2494 /// assert_eq!("foo", Path::new("foo.tar.gz").file_prefix().unwrap());
2498 /// This method is similar to [`Path::file_stem`], which extracts the portion of the file name
2499 /// before the *last* `.`
2501 /// [`Path::file_stem`]: Path::file_stem
2503 #[unstable(feature = "path_file_prefix", issue = "86319")]
2505 pub fn file_prefix(&self) -> Option
<&OsStr
> {
2506 self.file_name().map(split_file_at_dot
).and_then(|(before
, _after
)| Some(before
))
2509 /// Extracts the extension (without the leading dot) of [`self.file_name`], if possible.
2511 /// The extension is:
2513 /// * [`None`], if there is no file name;
2514 /// * [`None`], if there is no embedded `.`;
2515 /// * [`None`], if the file name begins with `.` and has no other `.`s within;
2516 /// * Otherwise, the portion of the file name after the final `.`
2518 /// [`self.file_name`]: Path::file_name
2523 /// use std::path::Path;
2525 /// assert_eq!("rs", Path::new("foo.rs").extension().unwrap());
2526 /// assert_eq!("gz", Path::new("foo.tar.gz").extension().unwrap());
2528 #[stable(feature = "rust1", since = "1.0.0")]
2530 pub fn extension(&self) -> Option
<&OsStr
> {
2531 self.file_name().map(rsplit_file_at_dot
).and_then(|(before
, after
)| before
.and(after
))
2534 /// Creates an owned [`PathBuf`] with `path` adjoined to `self`.
2536 /// If `path` is absolute, it replaces the current path.
2538 /// See [`PathBuf::push`] for more details on what it means to adjoin a path.
2543 /// use std::path::{Path, PathBuf};
2545 /// assert_eq!(Path::new("/etc").join("passwd"), PathBuf::from("/etc/passwd"));
2546 /// assert_eq!(Path::new("/etc").join("/bin/sh"), PathBuf::from("/bin/sh"));
2548 #[stable(feature = "rust1", since = "1.0.0")]
2550 pub fn join
<P
: AsRef
<Path
>>(&self, path
: P
) -> PathBuf
{
2551 self._join(path
.as_ref())
2554 fn _join(&self, path
: &Path
) -> PathBuf
{
2555 let mut buf
= self.to_path_buf();
2560 /// Creates an owned [`PathBuf`] like `self` but with the given file name.
2562 /// See [`PathBuf::set_file_name`] for more details.
2567 /// use std::path::{Path, PathBuf};
2569 /// let path = Path::new("/tmp/foo.png");
2570 /// assert_eq!(path.with_file_name("bar"), PathBuf::from("/tmp/bar"));
2571 /// assert_eq!(path.with_file_name("bar.txt"), PathBuf::from("/tmp/bar.txt"));
2573 /// let path = Path::new("/tmp");
2574 /// assert_eq!(path.with_file_name("var"), PathBuf::from("/var"));
2576 #[stable(feature = "rust1", since = "1.0.0")]
2578 pub fn with_file_name
<S
: AsRef
<OsStr
>>(&self, file_name
: S
) -> PathBuf
{
2579 self._with_file_name(file_name
.as_ref())
2582 fn _with_file_name(&self, file_name
: &OsStr
) -> PathBuf
{
2583 let mut buf
= self.to_path_buf();
2584 buf
.set_file_name(file_name
);
2588 /// Creates an owned [`PathBuf`] like `self` but with the given extension.
2590 /// See [`PathBuf::set_extension`] for more details.
2595 /// use std::path::{Path, PathBuf};
2597 /// let path = Path::new("foo.rs");
2598 /// assert_eq!(path.with_extension("txt"), PathBuf::from("foo.txt"));
2600 /// let path = Path::new("foo.tar.gz");
2601 /// assert_eq!(path.with_extension(""), PathBuf::from("foo.tar"));
2602 /// assert_eq!(path.with_extension("xz"), PathBuf::from("foo.tar.xz"));
2603 /// assert_eq!(path.with_extension("").with_extension("txt"), PathBuf::from("foo.txt"));
2605 #[stable(feature = "rust1", since = "1.0.0")]
2606 pub fn with_extension
<S
: AsRef
<OsStr
>>(&self, extension
: S
) -> PathBuf
{
2607 self._with_extension(extension
.as_ref())
2610 fn _with_extension(&self, extension
: &OsStr
) -> PathBuf
{
2611 let self_len
= self.as_os_str().len();
2612 let self_bytes
= self.as_os_str().as_encoded_bytes();
2614 let (new_capacity
, slice_to_copy
) = match self.extension() {
2616 // Enough capacity for the extension and the dot
2617 let capacity
= self_len
+ extension
.len() + 1;
2618 let whole_path
= self_bytes
.iter();
2619 (capacity
, whole_path
)
2621 Some(previous_extension
) => {
2622 let capacity
= self_len
+ extension
.len() - previous_extension
.len();
2623 let path_till_dot
= self_bytes
[..self_len
- previous_extension
.len()].iter();
2624 (capacity
, path_till_dot
)
2628 let mut new_path
= PathBuf
::with_capacity(new_capacity
);
2629 new_path
.as_mut_vec().extend(slice_to_copy
);
2630 new_path
.set_extension(extension
);
2634 /// Produces an iterator over the [`Component`]s of the path.
2636 /// When parsing the path, there is a small amount of normalization:
2638 /// * Repeated separators are ignored, so `a/b` and `a//b` both have
2639 /// `a` and `b` as components.
2641 /// * Occurrences of `.` are normalized away, except if they are at the
2642 /// beginning of the path. For example, `a/./b`, `a/b/`, `a/b/.` and
2643 /// `a/b` all have `a` and `b` as components, but `./a/b` starts with
2644 /// an additional [`CurDir`] component.
2646 /// * A trailing slash is normalized away, `/a/b` and `/a/b/` are equivalent.
2648 /// Note that no other normalization takes place; in particular, `a/c`
2649 /// and `a/b/../c` are distinct, to account for the possibility that `b`
2650 /// is a symbolic link (so its parent isn't `a`).
2655 /// use std::path::{Path, Component};
2656 /// use std::ffi::OsStr;
2658 /// let mut components = Path::new("/tmp/foo.txt").components();
2660 /// assert_eq!(components.next(), Some(Component::RootDir));
2661 /// assert_eq!(components.next(), Some(Component::Normal(OsStr::new("tmp"))));
2662 /// assert_eq!(components.next(), Some(Component::Normal(OsStr::new("foo.txt"))));
2663 /// assert_eq!(components.next(), None)
2666 /// [`CurDir`]: Component::CurDir
2667 #[stable(feature = "rust1", since = "1.0.0")]
2668 pub fn components(&self) -> Components
<'_
> {
2669 let prefix
= parse_prefix(self.as_os_str());
2671 path
: self.as_u8_slice(),
2673 has_physical_root
: has_physical_root(self.as_u8_slice(), prefix
)
2674 || has_redox_scheme(self.as_u8_slice()),
2675 front
: State
::Prefix
,
2680 /// Produces an iterator over the path's components viewed as [`OsStr`]
2683 /// For more information about the particulars of how the path is separated
2684 /// into components, see [`components`].
2686 /// [`components`]: Path::components
2691 /// use std::path::{self, Path};
2692 /// use std::ffi::OsStr;
2694 /// let mut it = Path::new("/tmp/foo.txt").iter();
2695 /// assert_eq!(it.next(), Some(OsStr::new(&path::MAIN_SEPARATOR.to_string())));
2696 /// assert_eq!(it.next(), Some(OsStr::new("tmp")));
2697 /// assert_eq!(it.next(), Some(OsStr::new("foo.txt")));
2698 /// assert_eq!(it.next(), None)
2700 #[stable(feature = "rust1", since = "1.0.0")]
2702 pub fn iter(&self) -> Iter
<'_
> {
2703 Iter { inner: self.components() }
2706 /// Returns an object that implements [`Display`] for safely printing paths
2707 /// that may contain non-Unicode data. This may perform lossy conversion,
2708 /// depending on the platform. If you would like an implementation which
2709 /// escapes the path please use [`Debug`] instead.
2711 /// [`Display`]: fmt::Display
2712 /// [`Debug`]: fmt::Debug
2717 /// use std::path::Path;
2719 /// let path = Path::new("/tmp/foo.rs");
2721 /// println!("{}", path.display());
2723 #[stable(feature = "rust1", since = "1.0.0")]
2724 #[must_use = "this does not display the path, \
2725 it returns an object that can be displayed"]
2727 pub fn display(&self) -> Display
<'_
> {
2728 Display { path: self }
2731 /// Queries the file system to get information about a file, directory, etc.
2733 /// This function will traverse symbolic links to query information about the
2734 /// destination file.
2736 /// This is an alias to [`fs::metadata`].
2741 /// use std::path::Path;
2743 /// let path = Path::new("/Minas/tirith");
2744 /// let metadata = path.metadata().expect("metadata call failed");
2745 /// println!("{:?}", metadata.file_type());
2747 #[stable(feature = "path_ext", since = "1.5.0")]
2749 pub fn metadata(&self) -> io
::Result
<fs
::Metadata
> {
2753 /// Queries the metadata about a file without following symlinks.
2755 /// This is an alias to [`fs::symlink_metadata`].
2760 /// use std::path::Path;
2762 /// let path = Path::new("/Minas/tirith");
2763 /// let metadata = path.symlink_metadata().expect("symlink_metadata call failed");
2764 /// println!("{:?}", metadata.file_type());
2766 #[stable(feature = "path_ext", since = "1.5.0")]
2768 pub fn symlink_metadata(&self) -> io
::Result
<fs
::Metadata
> {
2769 fs
::symlink_metadata(self)
2772 /// Returns the canonical, absolute form of the path with all intermediate
2773 /// components normalized and symbolic links resolved.
2775 /// This is an alias to [`fs::canonicalize`].
2780 /// use std::path::{Path, PathBuf};
2782 /// let path = Path::new("/foo/test/../test/bar.rs");
2783 /// assert_eq!(path.canonicalize().unwrap(), PathBuf::from("/foo/test/bar.rs"));
2785 #[stable(feature = "path_ext", since = "1.5.0")]
2787 pub fn canonicalize(&self) -> io
::Result
<PathBuf
> {
2788 fs
::canonicalize(self)
2791 /// Reads a symbolic link, returning the file that the link points to.
2793 /// This is an alias to [`fs::read_link`].
2798 /// use std::path::Path;
2800 /// let path = Path::new("/laputa/sky_castle.rs");
2801 /// let path_link = path.read_link().expect("read_link call failed");
2803 #[stable(feature = "path_ext", since = "1.5.0")]
2805 pub fn read_link(&self) -> io
::Result
<PathBuf
> {
2809 /// Returns an iterator over the entries within a directory.
2811 /// The iterator will yield instances of <code>[io::Result]<[fs::DirEntry]></code>. New
2812 /// errors may be encountered after an iterator is initially constructed.
2814 /// This is an alias to [`fs::read_dir`].
2819 /// use std::path::Path;
2821 /// let path = Path::new("/laputa");
2822 /// for entry in path.read_dir().expect("read_dir call failed") {
2823 /// if let Ok(entry) = entry {
2824 /// println!("{:?}", entry.path());
2828 #[stable(feature = "path_ext", since = "1.5.0")]
2830 pub fn read_dir(&self) -> io
::Result
<fs
::ReadDir
> {
2834 /// Returns `true` if the path points at an existing entity.
2836 /// Warning: this method may be error-prone, consider using [`try_exists()`] instead!
2837 /// It also has a risk of introducing time-of-check to time-of-use (TOCTOU) bugs.
2839 /// This function will traverse symbolic links to query information about the
2840 /// destination file.
2842 /// If you cannot access the metadata of the file, e.g. because of a
2843 /// permission error or broken symbolic links, this will return `false`.
2848 /// use std::path::Path;
2849 /// assert!(!Path::new("does_not_exist.txt").exists());
2854 /// This is a convenience function that coerces errors to false. If you want to
2855 /// check errors, call [`Path::try_exists`].
2857 /// [`try_exists()`]: Self::try_exists
2858 #[stable(feature = "path_ext", since = "1.5.0")]
2861 pub fn exists(&self) -> bool
{
2862 fs
::metadata(self).is_ok()
2865 /// Returns `Ok(true)` if the path points at an existing entity.
2867 /// This function will traverse symbolic links to query information about the
2868 /// destination file. In case of broken symbolic links this will return `Ok(false)`.
2870 /// [`Path::exists()`] only checks whether or not a path was both found and readable. By
2871 /// contrast, `try_exists` will return `Ok(true)` or `Ok(false)`, respectively, if the path
2872 /// was _verified_ to exist or not exist. If its existence can neither be confirmed nor
2873 /// denied, it will propagate an `Err(_)` instead. This can be the case if e.g. listing
2874 /// permission is denied on one of the parent directories.
2876 /// Note that while this avoids some pitfalls of the `exists()` method, it still can not
2877 /// prevent time-of-check to time-of-use (TOCTOU) bugs. You should only use it in scenarios
2878 /// where those bugs are not an issue.
2883 /// use std::path::Path;
2884 /// assert!(!Path::new("does_not_exist.txt").try_exists().expect("Can't check existence of file does_not_exist.txt"));
2885 /// assert!(Path::new("/root/secret_file.txt").try_exists().is_err());
2888 /// [`exists()`]: Self::exists
2889 #[stable(feature = "path_try_exists", since = "1.63.0")]
2891 pub fn try_exists(&self) -> io
::Result
<bool
> {
2892 fs
::try_exists(self)
2895 /// Returns `true` if the path exists on disk and is pointing at a regular file.
2897 /// This function will traverse symbolic links to query information about the
2898 /// destination file.
2900 /// If you cannot access the metadata of the file, e.g. because of a
2901 /// permission error or broken symbolic links, this will return `false`.
2906 /// use std::path::Path;
2907 /// assert_eq!(Path::new("./is_a_directory/").is_file(), false);
2908 /// assert_eq!(Path::new("a_file.txt").is_file(), true);
2913 /// This is a convenience function that coerces errors to false. If you want to
2914 /// check errors, call [`fs::metadata`] and handle its [`Result`]. Then call
2915 /// [`fs::Metadata::is_file`] if it was [`Ok`].
2917 /// When the goal is simply to read from (or write to) the source, the most
2918 /// reliable way to test the source can be read (or written to) is to open
2919 /// it. Only using `is_file` can break workflows like `diff <( prog_a )` on
2920 /// a Unix-like system for example. See [`fs::File::open`] or
2921 /// [`fs::OpenOptions::open`] for more information.
2922 #[stable(feature = "path_ext", since = "1.5.0")]
2924 pub fn is_file(&self) -> bool
{
2925 fs
::metadata(self).map(|m
| m
.is_file()).unwrap_or(false)
2928 /// Returns `true` if the path exists on disk and is pointing at a directory.
2930 /// This function will traverse symbolic links to query information about the
2931 /// destination file.
2933 /// If you cannot access the metadata of the file, e.g. because of a
2934 /// permission error or broken symbolic links, this will return `false`.
2939 /// use std::path::Path;
2940 /// assert_eq!(Path::new("./is_a_directory/").is_dir(), true);
2941 /// assert_eq!(Path::new("a_file.txt").is_dir(), false);
2946 /// This is a convenience function that coerces errors to false. If you want to
2947 /// check errors, call [`fs::metadata`] and handle its [`Result`]. Then call
2948 /// [`fs::Metadata::is_dir`] if it was [`Ok`].
2949 #[stable(feature = "path_ext", since = "1.5.0")]
2951 pub fn is_dir(&self) -> bool
{
2952 fs
::metadata(self).map(|m
| m
.is_dir()).unwrap_or(false)
2955 /// Returns `true` if the path exists on disk and is pointing at a symbolic link.
2957 /// This function will not traverse symbolic links.
2958 /// In case of a broken symbolic link this will also return true.
2960 /// If you cannot access the directory containing the file, e.g., because of a
2961 /// permission error, this will return false.
2965 #[cfg_attr(unix, doc = "```no_run")]
2966 #[cfg_attr(not(unix), doc = "```ignore")]
2967 /// use std::path::Path;
2968 /// use std::os::unix::fs::symlink;
2970 /// let link_path = Path::new("link");
2971 /// symlink("/origin_does_not_exist/", link_path).unwrap();
2972 /// assert_eq!(link_path.is_symlink(), true);
2973 /// assert_eq!(link_path.exists(), false);
2978 /// This is a convenience function that coerces errors to false. If you want to
2979 /// check errors, call [`fs::symlink_metadata`] and handle its [`Result`]. Then call
2980 /// [`fs::Metadata::is_symlink`] if it was [`Ok`].
2982 #[stable(feature = "is_symlink", since = "1.58.0")]
2983 pub fn is_symlink(&self) -> bool
{
2984 fs
::symlink_metadata(self).map(|m
| m
.is_symlink()).unwrap_or(false)
2987 /// Converts a [`Box<Path>`](Box) into a [`PathBuf`] without copying or
2989 #[stable(feature = "into_boxed_path", since = "1.20.0")]
2990 #[must_use = "`self` will be dropped if the result is not used"]
2991 pub fn into_path_buf(self: Box
<Path
>) -> PathBuf
{
2992 let rw
= Box
::into_raw(self) as *mut OsStr
;
2993 let inner
= unsafe { Box::from_raw(rw) }
;
2994 PathBuf { inner: OsString::from(inner) }
2998 #[stable(feature = "rust1", since = "1.0.0")]
2999 impl AsRef
<OsStr
> for Path
{
3001 fn as_ref(&self) -> &OsStr
{
3006 #[stable(feature = "rust1", since = "1.0.0")]
3007 impl fmt
::Debug
for Path
{
3008 fn fmt(&self, formatter
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
3009 fmt
::Debug
::fmt(&self.inner
, formatter
)
3013 /// Helper struct for safely printing paths with [`format!`] and `{}`.
3015 /// A [`Path`] might contain non-Unicode data. This `struct` implements the
3016 /// [`Display`] trait in a way that mitigates that. It is created by the
3017 /// [`display`](Path::display) method on [`Path`]. This may perform lossy
3018 /// conversion, depending on the platform. If you would like an implementation
3019 /// which escapes the path please use [`Debug`] instead.
3024 /// use std::path::Path;
3026 /// let path = Path::new("/tmp/foo.rs");
3028 /// println!("{}", path.display());
3031 /// [`Display`]: fmt::Display
3032 /// [`format!`]: crate::format
3033 #[stable(feature = "rust1", since = "1.0.0")]
3034 pub struct Display
<'a
> {
3038 #[stable(feature = "rust1", since = "1.0.0")]
3039 impl fmt
::Debug
for Display
<'_
> {
3040 fn fmt(&self, f
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
3041 fmt
::Debug
::fmt(&self.path
, f
)
3045 #[stable(feature = "rust1", since = "1.0.0")]
3046 impl fmt
::Display
for Display
<'_
> {
3047 fn fmt(&self, f
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
3048 self.path
.inner
.display(f
)
3052 #[stable(feature = "rust1", since = "1.0.0")]
3053 impl PartialEq
for Path
{
3055 fn eq(&self, other
: &Path
) -> bool
{
3056 self.components() == other
.components()
3060 #[stable(feature = "rust1", since = "1.0.0")]
3061 impl Hash
for Path
{
3062 fn hash
<H
: Hasher
>(&self, h
: &mut H
) {
3063 let bytes
= self.as_u8_slice();
3064 let (prefix_len
, verbatim
) = match parse_prefix(&self.inner
) {
3067 (prefix
.len(), prefix
.is_verbatim())
3071 let bytes
= &bytes
[prefix_len
..];
3073 let mut component_start
= 0;
3074 let mut bytes_hashed
= 0;
3076 for i
in 0..bytes
.len() {
3077 let is_sep
= if verbatim { is_verbatim_sep(bytes[i]) }
else { is_sep_byte(bytes[i]) }
;
3079 if i
> component_start
{
3080 let to_hash
= &bytes
[component_start
..i
];
3082 bytes_hashed
+= to_hash
.len();
3085 // skip over separator and optionally a following CurDir item
3086 // since components() would normalize these away.
3087 component_start
= i
+ 1;
3089 let tail
= &bytes
[component_start
..];
3092 component_start
+= match tail
{
3094 [b'
.'
, sep @ _
, ..] if is_sep_byte(*sep
) => 1,
3101 if component_start
< bytes
.len() {
3102 let to_hash
= &bytes
[component_start
..];
3104 bytes_hashed
+= to_hash
.len();
3107 h
.write_usize(bytes_hashed
);
3111 #[stable(feature = "rust1", since = "1.0.0")]
3114 #[stable(feature = "rust1", since = "1.0.0")]
3115 impl PartialOrd
for Path
{
3117 fn partial_cmp(&self, other
: &Path
) -> Option
<cmp
::Ordering
> {
3118 Some(compare_components(self.components(), other
.components()))
3122 #[stable(feature = "rust1", since = "1.0.0")]
3125 fn cmp(&self, other
: &Path
) -> cmp
::Ordering
{
3126 compare_components(self.components(), other
.components())
3130 #[stable(feature = "rust1", since = "1.0.0")]
3131 impl AsRef
<Path
> for Path
{
3133 fn as_ref(&self) -> &Path
{
3138 #[stable(feature = "rust1", since = "1.0.0")]
3139 impl AsRef
<Path
> for OsStr
{
3141 fn as_ref(&self) -> &Path
{
3146 #[stable(feature = "cow_os_str_as_ref_path", since = "1.8.0")]
3147 impl AsRef
<Path
> for Cow
<'_
, OsStr
> {
3149 fn as_ref(&self) -> &Path
{
3154 #[stable(feature = "rust1", since = "1.0.0")]
3155 impl AsRef
<Path
> for OsString
{
3157 fn as_ref(&self) -> &Path
{
3162 #[stable(feature = "rust1", since = "1.0.0")]
3163 impl AsRef
<Path
> for str {
3165 fn as_ref(&self) -> &Path
{
3170 #[stable(feature = "rust1", since = "1.0.0")]
3171 impl AsRef
<Path
> for String
{
3173 fn as_ref(&self) -> &Path
{
3178 #[stable(feature = "rust1", since = "1.0.0")]
3179 impl AsRef
<Path
> for PathBuf
{
3181 fn as_ref(&self) -> &Path
{
3186 #[stable(feature = "path_into_iter", since = "1.6.0")]
3187 impl<'a
> IntoIterator
for &'a PathBuf
{
3188 type Item
= &'a OsStr
;
3189 type IntoIter
= Iter
<'a
>;
3191 fn into_iter(self) -> Iter
<'a
> {
3196 #[stable(feature = "path_into_iter", since = "1.6.0")]
3197 impl<'a
> IntoIterator
for &'a Path
{
3198 type Item
= &'a OsStr
;
3199 type IntoIter
= Iter
<'a
>;
3201 fn into_iter(self) -> Iter
<'a
> {
3206 macro_rules
! impl_cmp
{
3207 (<$
($life
:lifetime
),*> $lhs
:ty
, $rhs
: ty
) => {
3208 #[stable(feature = "partialeq_path", since = "1.6.0")]
3209 impl<$
($life
),*> PartialEq
<$rhs
> for $lhs
{
3211 fn eq(&self, other
: &$rhs
) -> bool
{
3212 <Path
as PartialEq
>::eq(self, other
)
3216 #[stable(feature = "partialeq_path", since = "1.6.0")]
3217 impl<$
($life
),*> PartialEq
<$lhs
> for $rhs
{
3219 fn eq(&self, other
: &$lhs
) -> bool
{
3220 <Path
as PartialEq
>::eq(self, other
)
3224 #[stable(feature = "cmp_path", since = "1.8.0")]
3225 impl<$
($life
),*> PartialOrd
<$rhs
> for $lhs
{
3227 fn partial_cmp(&self, other
: &$rhs
) -> Option
<cmp
::Ordering
> {
3228 <Path
as PartialOrd
>::partial_cmp(self, other
)
3232 #[stable(feature = "cmp_path", since = "1.8.0")]
3233 impl<$
($life
),*> PartialOrd
<$lhs
> for $rhs
{
3235 fn partial_cmp(&self, other
: &$lhs
) -> Option
<cmp
::Ordering
> {
3236 <Path
as PartialOrd
>::partial_cmp(self, other
)
3242 impl_cmp
!(<> PathBuf
, Path
);
3243 impl_cmp
!(<'a
> PathBuf
, &'a Path
);
3244 impl_cmp
!(<'a
> Cow
<'a
, Path
>, Path
);
3245 impl_cmp
!(<'a
, 'b
> Cow
<'a
, Path
>, &'b Path
);
3246 impl_cmp
!(<'a
> Cow
<'a
, Path
>, PathBuf
);
3248 macro_rules
! impl_cmp_os_str
{
3249 (<$
($life
:lifetime
),*> $lhs
:ty
, $rhs
: ty
) => {
3250 #[stable(feature = "cmp_path", since = "1.8.0")]
3251 impl<$
($life
),*> PartialEq
<$rhs
> for $lhs
{
3253 fn eq(&self, other
: &$rhs
) -> bool
{
3254 <Path
as PartialEq
>::eq(self, other
.as_ref())
3258 #[stable(feature = "cmp_path", since = "1.8.0")]
3259 impl<$
($life
),*> PartialEq
<$lhs
> for $rhs
{
3261 fn eq(&self, other
: &$lhs
) -> bool
{
3262 <Path
as PartialEq
>::eq(self.as_ref(), other
)
3266 #[stable(feature = "cmp_path", since = "1.8.0")]
3267 impl<$
($life
),*> PartialOrd
<$rhs
> for $lhs
{
3269 fn partial_cmp(&self, other
: &$rhs
) -> Option
<cmp
::Ordering
> {
3270 <Path
as PartialOrd
>::partial_cmp(self, other
.as_ref())
3274 #[stable(feature = "cmp_path", since = "1.8.0")]
3275 impl<$
($life
),*> PartialOrd
<$lhs
> for $rhs
{
3277 fn partial_cmp(&self, other
: &$lhs
) -> Option
<cmp
::Ordering
> {
3278 <Path
as PartialOrd
>::partial_cmp(self.as_ref(), other
)
3284 impl_cmp_os_str
!(<> PathBuf
, OsStr
);
3285 impl_cmp_os_str
!(<'a
> PathBuf
, &'a OsStr
);
3286 impl_cmp_os_str
!(<'a
> PathBuf
, Cow
<'a
, OsStr
>);
3287 impl_cmp_os_str
!(<> PathBuf
, OsString
);
3288 impl_cmp_os_str
!(<> Path
, OsStr
);
3289 impl_cmp_os_str
!(<'a
> Path
, &'a OsStr
);
3290 impl_cmp_os_str
!(<'a
> Path
, Cow
<'a
, OsStr
>);
3291 impl_cmp_os_str
!(<> Path
, OsString
);
3292 impl_cmp_os_str
!(<'a
> &'a Path
, OsStr
);
3293 impl_cmp_os_str
!(<'a
, 'b
> &'a Path
, Cow
<'b
, OsStr
>);
3294 impl_cmp_os_str
!(<'a
> &'a Path
, OsString
);
3295 impl_cmp_os_str
!(<'a
> Cow
<'a
, Path
>, OsStr
);
3296 impl_cmp_os_str
!(<'a
, 'b
> Cow
<'a
, Path
>, &'b OsStr
);
3297 impl_cmp_os_str
!(<'a
> Cow
<'a
, Path
>, OsString
);
3299 #[stable(since = "1.7.0", feature = "strip_prefix")]
3300 impl fmt
::Display
for StripPrefixError
{
3301 #[allow(deprecated, deprecated_in_future)]
3302 fn fmt(&self, f
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
3303 self.description().fmt(f
)
3307 #[stable(since = "1.7.0", feature = "strip_prefix")]
3308 impl Error
for StripPrefixError
{
3309 #[allow(deprecated)]
3310 fn description(&self) -> &str {
3315 /// Makes the path absolute without accessing the filesystem.
3317 /// If the path is relative, the current directory is used as the base directory.
3318 /// All intermediate components will be resolved according to platforms-specific
3319 /// rules but unlike [`canonicalize`][crate::fs::canonicalize] this does not
3320 /// resolve symlinks and may succeed even if the path does not exist.
3322 /// If the `path` is empty or getting the
3323 /// [current directory][crate::env::current_dir] fails then an error will be
3331 /// #![feature(absolute_path)]
3333 /// fn main() -> std::io::Result<()> {
3334 /// use std::path::{self, Path};
3336 /// // Relative to absolute
3337 /// let absolute = path::absolute("foo/./bar")?;
3338 /// assert!(absolute.ends_with("foo/bar"));
3340 /// // Absolute to absolute
3341 /// let absolute = path::absolute("/foo//test/.././bar.rs")?;
3342 /// assert_eq!(absolute, Path::new("/foo/test/../bar.rs"));
3345 /// # #[cfg(not(unix))]
3349 /// The path is resolved using [POSIX semantics][posix-semantics] except that
3350 /// it stops short of resolving symlinks. This means it will keep `..`
3351 /// components and trailing slashes.
3353 /// ## Windows paths
3356 /// #![feature(absolute_path)]
3357 /// # #[cfg(windows)]
3358 /// fn main() -> std::io::Result<()> {
3359 /// use std::path::{self, Path};
3361 /// // Relative to absolute
3362 /// let absolute = path::absolute("foo/./bar")?;
3363 /// assert!(absolute.ends_with(r"foo\bar"));
3365 /// // Absolute to absolute
3366 /// let absolute = path::absolute(r"C:\foo//test\..\./bar.rs")?;
3368 /// assert_eq!(absolute, Path::new(r"C:\foo\bar.rs"));
3371 /// # #[cfg(not(windows))]
3375 /// For verbatim paths this will simply return the path as given. For other
3376 /// paths this is currently equivalent to calling [`GetFullPathNameW`][windows-path]
3377 /// This may change in the future.
3379 /// [posix-semantics]: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap04.html#tag_04_13
3380 /// [windows-path]: https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-getfullpathnamew
3381 #[unstable(feature = "absolute_path", issue = "92750")]
3382 pub fn absolute
<P
: AsRef
<Path
>>(path
: P
) -> io
::Result
<PathBuf
> {
3383 let path
= path
.as_ref();
3384 if path
.as_os_str().is_empty() {
3385 Err(io
::const_io_error
!(io
::ErrorKind
::InvalidInput
, "cannot make an empty path absolute",))
3387 sys
::path
::absolute(path
)