fish-shell/tests/checks/path.fish

315 lines
7.0 KiB
Fish
Raw Normal View History

Add "path" builtin This adds a "path" builtin that can handle paths. Implemented so far: - "path filter PATHS", filters paths according to existence and optionally type and permissions - "path base" and "path dir", run basename and dirname, respectively - "path extension PATHS", prints the extension, if any - "path strip-extension", prints the path without the extension - "path normalize PATHS", normalizes paths - removing "/./" components - and such. - "path real", does realpath - i.e. normalizing *and* link resolution. Some of these - base, dir, {strip-,}extension and normalize operate on the paths only as strings, so they handle nonexistent paths. filter and real ignore any nonexistent paths. All output is split explicitly, so paths with newlines in them are handled correctly. Alternatively, all subcommands have a "--null-input"/"-z" and "--null-output"/"-Z" option to handle null-terminated input and create null-terminated output. So find . -print0 | path base -z prints the basename of all files in the current directory, recursively. With "-Z" it also prints it null-separated. (if stdout is going to a command substitution, we probably want to skip this) All subcommands also have a "-q"/"--quiet" flag that tells them to skip output. They return true "when something happened". For match/filter that's when a file passed, for "base"/"dir"/"extension"/"strip-extension" that's when something about the path *changed*. Filtering --------- `filter` supports all the file*types* `test` has - "dir", "file", "link", "block"..., as well as the permissions - "read", "write", "exec" and things like "suid". It is missing the tty check and the check for the file being non-empty. The former is best done via `isatty`, the latter I don't think I've ever seen used. There currently is no way to only get "real" files, i.e. ignore links pointing to files. Examples -------- > path real /bin///sh /usr/bin/bash > path extension foo.mp4 mp4 > path extension ~/.config (nothing, because ".config" isn't an extension.)
2021-08-28 20:45:24 +08:00
#RUN: %fish %s
# The "path" builtin for dealing with paths
# Extension - for figuring out the file extension of a given path.
path extension /
or echo None
# CHECK:
Add "path" builtin This adds a "path" builtin that can handle paths. Implemented so far: - "path filter PATHS", filters paths according to existence and optionally type and permissions - "path base" and "path dir", run basename and dirname, respectively - "path extension PATHS", prints the extension, if any - "path strip-extension", prints the path without the extension - "path normalize PATHS", normalizes paths - removing "/./" components - and such. - "path real", does realpath - i.e. normalizing *and* link resolution. Some of these - base, dir, {strip-,}extension and normalize operate on the paths only as strings, so they handle nonexistent paths. filter and real ignore any nonexistent paths. All output is split explicitly, so paths with newlines in them are handled correctly. Alternatively, all subcommands have a "--null-input"/"-z" and "--null-output"/"-Z" option to handle null-terminated input and create null-terminated output. So find . -print0 | path base -z prints the basename of all files in the current directory, recursively. With "-Z" it also prints it null-separated. (if stdout is going to a command substitution, we probably want to skip this) All subcommands also have a "-q"/"--quiet" flag that tells them to skip output. They return true "when something happened". For match/filter that's when a file passed, for "base"/"dir"/"extension"/"strip-extension" that's when something about the path *changed*. Filtering --------- `filter` supports all the file*types* `test` has - "dir", "file", "link", "block"..., as well as the permissions - "read", "write", "exec" and things like "suid". It is missing the tty check and the check for the file being non-empty. The former is best done via `isatty`, the latter I don't think I've ever seen used. There currently is no way to only get "real" files, i.e. ignore links pointing to files. Examples -------- > path real /bin///sh /usr/bin/bash > path extension foo.mp4 mp4 > path extension ~/.config (nothing, because ".config" isn't an extension.)
2021-08-28 20:45:24 +08:00
# CHECK: None
# No extension
path extension /.
or echo Filename is just a dot, no extension
# CHECK:
Add "path" builtin This adds a "path" builtin that can handle paths. Implemented so far: - "path filter PATHS", filters paths according to existence and optionally type and permissions - "path base" and "path dir", run basename and dirname, respectively - "path extension PATHS", prints the extension, if any - "path strip-extension", prints the path without the extension - "path normalize PATHS", normalizes paths - removing "/./" components - and such. - "path real", does realpath - i.e. normalizing *and* link resolution. Some of these - base, dir, {strip-,}extension and normalize operate on the paths only as strings, so they handle nonexistent paths. filter and real ignore any nonexistent paths. All output is split explicitly, so paths with newlines in them are handled correctly. Alternatively, all subcommands have a "--null-input"/"-z" and "--null-output"/"-Z" option to handle null-terminated input and create null-terminated output. So find . -print0 | path base -z prints the basename of all files in the current directory, recursively. With "-Z" it also prints it null-separated. (if stdout is going to a command substitution, we probably want to skip this) All subcommands also have a "-q"/"--quiet" flag that tells them to skip output. They return true "when something happened". For match/filter that's when a file passed, for "base"/"dir"/"extension"/"strip-extension" that's when something about the path *changed*. Filtering --------- `filter` supports all the file*types* `test` has - "dir", "file", "link", "block"..., as well as the permissions - "read", "write", "exec" and things like "suid". It is missing the tty check and the check for the file being non-empty. The former is best done via `isatty`, the latter I don't think I've ever seen used. There currently is no way to only get "real" files, i.e. ignore links pointing to files. Examples -------- > path real /bin///sh /usr/bin/bash > path extension foo.mp4 mp4 > path extension ~/.config (nothing, because ".config" isn't an extension.)
2021-08-28 20:45:24 +08:00
# CHECK: Filename is just a dot, no extension
# No extension - ".foo" is the filename
path extension /.foo
or echo None again
# CHECK:
Add "path" builtin This adds a "path" builtin that can handle paths. Implemented so far: - "path filter PATHS", filters paths according to existence and optionally type and permissions - "path base" and "path dir", run basename and dirname, respectively - "path extension PATHS", prints the extension, if any - "path strip-extension", prints the path without the extension - "path normalize PATHS", normalizes paths - removing "/./" components - and such. - "path real", does realpath - i.e. normalizing *and* link resolution. Some of these - base, dir, {strip-,}extension and normalize operate on the paths only as strings, so they handle nonexistent paths. filter and real ignore any nonexistent paths. All output is split explicitly, so paths with newlines in them are handled correctly. Alternatively, all subcommands have a "--null-input"/"-z" and "--null-output"/"-Z" option to handle null-terminated input and create null-terminated output. So find . -print0 | path base -z prints the basename of all files in the current directory, recursively. With "-Z" it also prints it null-separated. (if stdout is going to a command substitution, we probably want to skip this) All subcommands also have a "-q"/"--quiet" flag that tells them to skip output. They return true "when something happened". For match/filter that's when a file passed, for "base"/"dir"/"extension"/"strip-extension" that's when something about the path *changed*. Filtering --------- `filter` supports all the file*types* `test` has - "dir", "file", "link", "block"..., as well as the permissions - "read", "write", "exec" and things like "suid". It is missing the tty check and the check for the file being non-empty. The former is best done via `isatty`, the latter I don't think I've ever seen used. There currently is no way to only get "real" files, i.e. ignore links pointing to files. Examples -------- > path real /bin///sh /usr/bin/bash > path extension foo.mp4 mp4 > path extension ~/.config (nothing, because ".config" isn't an extension.)
2021-08-28 20:45:24 +08:00
# CHECK: None again
path extension /foo
or echo None once more
# CHECK:
Add "path" builtin This adds a "path" builtin that can handle paths. Implemented so far: - "path filter PATHS", filters paths according to existence and optionally type and permissions - "path base" and "path dir", run basename and dirname, respectively - "path extension PATHS", prints the extension, if any - "path strip-extension", prints the path without the extension - "path normalize PATHS", normalizes paths - removing "/./" components - and such. - "path real", does realpath - i.e. normalizing *and* link resolution. Some of these - base, dir, {strip-,}extension and normalize operate on the paths only as strings, so they handle nonexistent paths. filter and real ignore any nonexistent paths. All output is split explicitly, so paths with newlines in them are handled correctly. Alternatively, all subcommands have a "--null-input"/"-z" and "--null-output"/"-Z" option to handle null-terminated input and create null-terminated output. So find . -print0 | path base -z prints the basename of all files in the current directory, recursively. With "-Z" it also prints it null-separated. (if stdout is going to a command substitution, we probably want to skip this) All subcommands also have a "-q"/"--quiet" flag that tells them to skip output. They return true "when something happened". For match/filter that's when a file passed, for "base"/"dir"/"extension"/"strip-extension" that's when something about the path *changed*. Filtering --------- `filter` supports all the file*types* `test` has - "dir", "file", "link", "block"..., as well as the permissions - "read", "write", "exec" and things like "suid". It is missing the tty check and the check for the file being non-empty. The former is best done via `isatty`, the latter I don't think I've ever seen used. There currently is no way to only get "real" files, i.e. ignore links pointing to files. Examples -------- > path real /bin///sh /usr/bin/bash > path extension foo.mp4 mp4 > path extension ~/.config (nothing, because ".config" isn't an extension.)
2021-08-28 20:45:24 +08:00
# CHECK: None once more
path extension /foo.txt
and echo Success
# CHECK: .txt
Add "path" builtin This adds a "path" builtin that can handle paths. Implemented so far: - "path filter PATHS", filters paths according to existence and optionally type and permissions - "path base" and "path dir", run basename and dirname, respectively - "path extension PATHS", prints the extension, if any - "path strip-extension", prints the path without the extension - "path normalize PATHS", normalizes paths - removing "/./" components - and such. - "path real", does realpath - i.e. normalizing *and* link resolution. Some of these - base, dir, {strip-,}extension and normalize operate on the paths only as strings, so they handle nonexistent paths. filter and real ignore any nonexistent paths. All output is split explicitly, so paths with newlines in them are handled correctly. Alternatively, all subcommands have a "--null-input"/"-z" and "--null-output"/"-Z" option to handle null-terminated input and create null-terminated output. So find . -print0 | path base -z prints the basename of all files in the current directory, recursively. With "-Z" it also prints it null-separated. (if stdout is going to a command substitution, we probably want to skip this) All subcommands also have a "-q"/"--quiet" flag that tells them to skip output. They return true "when something happened". For match/filter that's when a file passed, for "base"/"dir"/"extension"/"strip-extension" that's when something about the path *changed*. Filtering --------- `filter` supports all the file*types* `test` has - "dir", "file", "link", "block"..., as well as the permissions - "read", "write", "exec" and things like "suid". It is missing the tty check and the check for the file being non-empty. The former is best done via `isatty`, the latter I don't think I've ever seen used. There currently is no way to only get "real" files, i.e. ignore links pointing to files. Examples -------- > path real /bin///sh /usr/bin/bash > path extension foo.mp4 mp4 > path extension ~/.config (nothing, because ".config" isn't an extension.)
2021-08-28 20:45:24 +08:00
# CHECK: Success
path extension /foo.txt/bar
or echo Not even here
# CHECK:
Add "path" builtin This adds a "path" builtin that can handle paths. Implemented so far: - "path filter PATHS", filters paths according to existence and optionally type and permissions - "path base" and "path dir", run basename and dirname, respectively - "path extension PATHS", prints the extension, if any - "path strip-extension", prints the path without the extension - "path normalize PATHS", normalizes paths - removing "/./" components - and such. - "path real", does realpath - i.e. normalizing *and* link resolution. Some of these - base, dir, {strip-,}extension and normalize operate on the paths only as strings, so they handle nonexistent paths. filter and real ignore any nonexistent paths. All output is split explicitly, so paths with newlines in them are handled correctly. Alternatively, all subcommands have a "--null-input"/"-z" and "--null-output"/"-Z" option to handle null-terminated input and create null-terminated output. So find . -print0 | path base -z prints the basename of all files in the current directory, recursively. With "-Z" it also prints it null-separated. (if stdout is going to a command substitution, we probably want to skip this) All subcommands also have a "-q"/"--quiet" flag that tells them to skip output. They return true "when something happened". For match/filter that's when a file passed, for "base"/"dir"/"extension"/"strip-extension" that's when something about the path *changed*. Filtering --------- `filter` supports all the file*types* `test` has - "dir", "file", "link", "block"..., as well as the permissions - "read", "write", "exec" and things like "suid". It is missing the tty check and the check for the file being non-empty. The former is best done via `isatty`, the latter I don't think I've ever seen used. There currently is no way to only get "real" files, i.e. ignore links pointing to files. Examples -------- > path real /bin///sh /usr/bin/bash > path extension foo.mp4 mp4 > path extension ~/.config (nothing, because ".config" isn't an extension.)
2021-08-28 20:45:24 +08:00
# CHECK: Not even here
path extension . ..
or echo No extension
# CHECK:
Add "path" builtin This adds a "path" builtin that can handle paths. Implemented so far: - "path filter PATHS", filters paths according to existence and optionally type and permissions - "path base" and "path dir", run basename and dirname, respectively - "path extension PATHS", prints the extension, if any - "path strip-extension", prints the path without the extension - "path normalize PATHS", normalizes paths - removing "/./" components - and such. - "path real", does realpath - i.e. normalizing *and* link resolution. Some of these - base, dir, {strip-,}extension and normalize operate on the paths only as strings, so they handle nonexistent paths. filter and real ignore any nonexistent paths. All output is split explicitly, so paths with newlines in them are handled correctly. Alternatively, all subcommands have a "--null-input"/"-z" and "--null-output"/"-Z" option to handle null-terminated input and create null-terminated output. So find . -print0 | path base -z prints the basename of all files in the current directory, recursively. With "-Z" it also prints it null-separated. (if stdout is going to a command substitution, we probably want to skip this) All subcommands also have a "-q"/"--quiet" flag that tells them to skip output. They return true "when something happened". For match/filter that's when a file passed, for "base"/"dir"/"extension"/"strip-extension" that's when something about the path *changed*. Filtering --------- `filter` supports all the file*types* `test` has - "dir", "file", "link", "block"..., as well as the permissions - "read", "write", "exec" and things like "suid". It is missing the tty check and the check for the file being non-empty. The former is best done via `isatty`, the latter I don't think I've ever seen used. There currently is no way to only get "real" files, i.e. ignore links pointing to files. Examples -------- > path real /bin///sh /usr/bin/bash > path extension foo.mp4 mp4 > path extension ~/.config (nothing, because ".config" isn't an extension.)
2021-08-28 20:45:24 +08:00
# CHECK: No extension
path extension ./foo.mp4
# CHECK: .mp4
Add "path" builtin This adds a "path" builtin that can handle paths. Implemented so far: - "path filter PATHS", filters paths according to existence and optionally type and permissions - "path base" and "path dir", run basename and dirname, respectively - "path extension PATHS", prints the extension, if any - "path strip-extension", prints the path without the extension - "path normalize PATHS", normalizes paths - removing "/./" components - and such. - "path real", does realpath - i.e. normalizing *and* link resolution. Some of these - base, dir, {strip-,}extension and normalize operate on the paths only as strings, so they handle nonexistent paths. filter and real ignore any nonexistent paths. All output is split explicitly, so paths with newlines in them are handled correctly. Alternatively, all subcommands have a "--null-input"/"-z" and "--null-output"/"-Z" option to handle null-terminated input and create null-terminated output. So find . -print0 | path base -z prints the basename of all files in the current directory, recursively. With "-Z" it also prints it null-separated. (if stdout is going to a command substitution, we probably want to skip this) All subcommands also have a "-q"/"--quiet" flag that tells them to skip output. They return true "when something happened". For match/filter that's when a file passed, for "base"/"dir"/"extension"/"strip-extension" that's when something about the path *changed*. Filtering --------- `filter` supports all the file*types* `test` has - "dir", "file", "link", "block"..., as well as the permissions - "read", "write", "exec" and things like "suid". It is missing the tty check and the check for the file being non-empty. The former is best done via `isatty`, the latter I don't think I've ever seen used. There currently is no way to only get "real" files, i.e. ignore links pointing to files. Examples -------- > path real /bin///sh /usr/bin/bash > path extension foo.mp4 mp4 > path extension ~/.config (nothing, because ".config" isn't an extension.)
2021-08-28 20:45:24 +08:00
path extension ../banana
# CHECK:
Add "path" builtin This adds a "path" builtin that can handle paths. Implemented so far: - "path filter PATHS", filters paths according to existence and optionally type and permissions - "path base" and "path dir", run basename and dirname, respectively - "path extension PATHS", prints the extension, if any - "path strip-extension", prints the path without the extension - "path normalize PATHS", normalizes paths - removing "/./" components - and such. - "path real", does realpath - i.e. normalizing *and* link resolution. Some of these - base, dir, {strip-,}extension and normalize operate on the paths only as strings, so they handle nonexistent paths. filter and real ignore any nonexistent paths. All output is split explicitly, so paths with newlines in them are handled correctly. Alternatively, all subcommands have a "--null-input"/"-z" and "--null-output"/"-Z" option to handle null-terminated input and create null-terminated output. So find . -print0 | path base -z prints the basename of all files in the current directory, recursively. With "-Z" it also prints it null-separated. (if stdout is going to a command substitution, we probably want to skip this) All subcommands also have a "-q"/"--quiet" flag that tells them to skip output. They return true "when something happened". For match/filter that's when a file passed, for "base"/"dir"/"extension"/"strip-extension" that's when something about the path *changed*. Filtering --------- `filter` supports all the file*types* `test` has - "dir", "file", "link", "block"..., as well as the permissions - "read", "write", "exec" and things like "suid". It is missing the tty check and the check for the file being non-empty. The former is best done via `isatty`, the latter I don't think I've ever seen used. There currently is no way to only get "real" files, i.e. ignore links pointing to files. Examples -------- > path real /bin///sh /usr/bin/bash > path extension foo.mp4 mp4 > path extension ~/.config (nothing, because ".config" isn't an extension.)
2021-08-28 20:45:24 +08:00
# nothing, status 1
echo $status
# CHECK: 1
path extension ~/.config
# CHECK:
Add "path" builtin This adds a "path" builtin that can handle paths. Implemented so far: - "path filter PATHS", filters paths according to existence and optionally type and permissions - "path base" and "path dir", run basename and dirname, respectively - "path extension PATHS", prints the extension, if any - "path strip-extension", prints the path without the extension - "path normalize PATHS", normalizes paths - removing "/./" components - and such. - "path real", does realpath - i.e. normalizing *and* link resolution. Some of these - base, dir, {strip-,}extension and normalize operate on the paths only as strings, so they handle nonexistent paths. filter and real ignore any nonexistent paths. All output is split explicitly, so paths with newlines in them are handled correctly. Alternatively, all subcommands have a "--null-input"/"-z" and "--null-output"/"-Z" option to handle null-terminated input and create null-terminated output. So find . -print0 | path base -z prints the basename of all files in the current directory, recursively. With "-Z" it also prints it null-separated. (if stdout is going to a command substitution, we probably want to skip this) All subcommands also have a "-q"/"--quiet" flag that tells them to skip output. They return true "when something happened". For match/filter that's when a file passed, for "base"/"dir"/"extension"/"strip-extension" that's when something about the path *changed*. Filtering --------- `filter` supports all the file*types* `test` has - "dir", "file", "link", "block"..., as well as the permissions - "read", "write", "exec" and things like "suid". It is missing the tty check and the check for the file being non-empty. The former is best done via `isatty`, the latter I don't think I've ever seen used. There currently is no way to only get "real" files, i.e. ignore links pointing to files. Examples -------- > path real /bin///sh /usr/bin/bash > path extension foo.mp4 mp4 > path extension ~/.config (nothing, because ".config" isn't an extension.)
2021-08-28 20:45:24 +08:00
# nothing, status 1
echo $status
# CHECK: 1
path extension ~/.config.d
# CHECK: .d
Add "path" builtin This adds a "path" builtin that can handle paths. Implemented so far: - "path filter PATHS", filters paths according to existence and optionally type and permissions - "path base" and "path dir", run basename and dirname, respectively - "path extension PATHS", prints the extension, if any - "path strip-extension", prints the path without the extension - "path normalize PATHS", normalizes paths - removing "/./" components - and such. - "path real", does realpath - i.e. normalizing *and* link resolution. Some of these - base, dir, {strip-,}extension and normalize operate on the paths only as strings, so they handle nonexistent paths. filter and real ignore any nonexistent paths. All output is split explicitly, so paths with newlines in them are handled correctly. Alternatively, all subcommands have a "--null-input"/"-z" and "--null-output"/"-Z" option to handle null-terminated input and create null-terminated output. So find . -print0 | path base -z prints the basename of all files in the current directory, recursively. With "-Z" it also prints it null-separated. (if stdout is going to a command substitution, we probably want to skip this) All subcommands also have a "-q"/"--quiet" flag that tells them to skip output. They return true "when something happened". For match/filter that's when a file passed, for "base"/"dir"/"extension"/"strip-extension" that's when something about the path *changed*. Filtering --------- `filter` supports all the file*types* `test` has - "dir", "file", "link", "block"..., as well as the permissions - "read", "write", "exec" and things like "suid". It is missing the tty check and the check for the file being non-empty. The former is best done via `isatty`, the latter I don't think I've ever seen used. There currently is no way to only get "real" files, i.e. ignore links pointing to files. Examples -------- > path real /bin///sh /usr/bin/bash > path extension foo.mp4 mp4 > path extension ~/.config (nothing, because ".config" isn't an extension.)
2021-08-28 20:45:24 +08:00
path extension ~/.config.
echo $status
# status 0
# CHECK: .
Add "path" builtin This adds a "path" builtin that can handle paths. Implemented so far: - "path filter PATHS", filters paths according to existence and optionally type and permissions - "path base" and "path dir", run basename and dirname, respectively - "path extension PATHS", prints the extension, if any - "path strip-extension", prints the path without the extension - "path normalize PATHS", normalizes paths - removing "/./" components - and such. - "path real", does realpath - i.e. normalizing *and* link resolution. Some of these - base, dir, {strip-,}extension and normalize operate on the paths only as strings, so they handle nonexistent paths. filter and real ignore any nonexistent paths. All output is split explicitly, so paths with newlines in them are handled correctly. Alternatively, all subcommands have a "--null-input"/"-z" and "--null-output"/"-Z" option to handle null-terminated input and create null-terminated output. So find . -print0 | path base -z prints the basename of all files in the current directory, recursively. With "-Z" it also prints it null-separated. (if stdout is going to a command substitution, we probably want to skip this) All subcommands also have a "-q"/"--quiet" flag that tells them to skip output. They return true "when something happened". For match/filter that's when a file passed, for "base"/"dir"/"extension"/"strip-extension" that's when something about the path *changed*. Filtering --------- `filter` supports all the file*types* `test` has - "dir", "file", "link", "block"..., as well as the permissions - "read", "write", "exec" and things like "suid". It is missing the tty check and the check for the file being non-empty. The former is best done via `isatty`, the latter I don't think I've ever seen used. There currently is no way to only get "real" files, i.e. ignore links pointing to files. Examples -------- > path real /bin///sh /usr/bin/bash > path extension foo.mp4 mp4 > path extension ~/.config (nothing, because ".config" isn't an extension.)
2021-08-28 20:45:24 +08:00
# CHECK: 0
path change-extension '' ./foo.mp4
Add "path" builtin This adds a "path" builtin that can handle paths. Implemented so far: - "path filter PATHS", filters paths according to existence and optionally type and permissions - "path base" and "path dir", run basename and dirname, respectively - "path extension PATHS", prints the extension, if any - "path strip-extension", prints the path without the extension - "path normalize PATHS", normalizes paths - removing "/./" components - and such. - "path real", does realpath - i.e. normalizing *and* link resolution. Some of these - base, dir, {strip-,}extension and normalize operate on the paths only as strings, so they handle nonexistent paths. filter and real ignore any nonexistent paths. All output is split explicitly, so paths with newlines in them are handled correctly. Alternatively, all subcommands have a "--null-input"/"-z" and "--null-output"/"-Z" option to handle null-terminated input and create null-terminated output. So find . -print0 | path base -z prints the basename of all files in the current directory, recursively. With "-Z" it also prints it null-separated. (if stdout is going to a command substitution, we probably want to skip this) All subcommands also have a "-q"/"--quiet" flag that tells them to skip output. They return true "when something happened". For match/filter that's when a file passed, for "base"/"dir"/"extension"/"strip-extension" that's when something about the path *changed*. Filtering --------- `filter` supports all the file*types* `test` has - "dir", "file", "link", "block"..., as well as the permissions - "read", "write", "exec" and things like "suid". It is missing the tty check and the check for the file being non-empty. The former is best done via `isatty`, the latter I don't think I've ever seen used. There currently is no way to only get "real" files, i.e. ignore links pointing to files. Examples -------- > path real /bin///sh /usr/bin/bash > path extension foo.mp4 mp4 > path extension ~/.config (nothing, because ".config" isn't an extension.)
2021-08-28 20:45:24 +08:00
# CHECK: ./foo
path change-extension wmv ./foo.mp4
# CHECK: ./foo.wmv
path change-extension .wmv ./foo.mp4
# CHECK: ./foo.wmv
path change-extension '' ../banana
Add "path" builtin This adds a "path" builtin that can handle paths. Implemented so far: - "path filter PATHS", filters paths according to existence and optionally type and permissions - "path base" and "path dir", run basename and dirname, respectively - "path extension PATHS", prints the extension, if any - "path strip-extension", prints the path without the extension - "path normalize PATHS", normalizes paths - removing "/./" components - and such. - "path real", does realpath - i.e. normalizing *and* link resolution. Some of these - base, dir, {strip-,}extension and normalize operate on the paths only as strings, so they handle nonexistent paths. filter and real ignore any nonexistent paths. All output is split explicitly, so paths with newlines in them are handled correctly. Alternatively, all subcommands have a "--null-input"/"-z" and "--null-output"/"-Z" option to handle null-terminated input and create null-terminated output. So find . -print0 | path base -z prints the basename of all files in the current directory, recursively. With "-Z" it also prints it null-separated. (if stdout is going to a command substitution, we probably want to skip this) All subcommands also have a "-q"/"--quiet" flag that tells them to skip output. They return true "when something happened". For match/filter that's when a file passed, for "base"/"dir"/"extension"/"strip-extension" that's when something about the path *changed*. Filtering --------- `filter` supports all the file*types* `test` has - "dir", "file", "link", "block"..., as well as the permissions - "read", "write", "exec" and things like "suid". It is missing the tty check and the check for the file being non-empty. The former is best done via `isatty`, the latter I don't think I've ever seen used. There currently is no way to only get "real" files, i.e. ignore links pointing to files. Examples -------- > path real /bin///sh /usr/bin/bash > path extension foo.mp4 mp4 > path extension ~/.config (nothing, because ".config" isn't an extension.)
2021-08-28 20:45:24 +08:00
# CHECK: ../banana
# still status 0, because there was an argument
Add "path" builtin This adds a "path" builtin that can handle paths. Implemented so far: - "path filter PATHS", filters paths according to existence and optionally type and permissions - "path base" and "path dir", run basename and dirname, respectively - "path extension PATHS", prints the extension, if any - "path strip-extension", prints the path without the extension - "path normalize PATHS", normalizes paths - removing "/./" components - and such. - "path real", does realpath - i.e. normalizing *and* link resolution. Some of these - base, dir, {strip-,}extension and normalize operate on the paths only as strings, so they handle nonexistent paths. filter and real ignore any nonexistent paths. All output is split explicitly, so paths with newlines in them are handled correctly. Alternatively, all subcommands have a "--null-input"/"-z" and "--null-output"/"-Z" option to handle null-terminated input and create null-terminated output. So find . -print0 | path base -z prints the basename of all files in the current directory, recursively. With "-Z" it also prints it null-separated. (if stdout is going to a command substitution, we probably want to skip this) All subcommands also have a "-q"/"--quiet" flag that tells them to skip output. They return true "when something happened". For match/filter that's when a file passed, for "base"/"dir"/"extension"/"strip-extension" that's when something about the path *changed*. Filtering --------- `filter` supports all the file*types* `test` has - "dir", "file", "link", "block"..., as well as the permissions - "read", "write", "exec" and things like "suid". It is missing the tty check and the check for the file being non-empty. The former is best done via `isatty`, the latter I don't think I've ever seen used. There currently is no way to only get "real" files, i.e. ignore links pointing to files. Examples -------- > path real /bin///sh /usr/bin/bash > path extension foo.mp4 mp4 > path extension ~/.config (nothing, because ".config" isn't an extension.)
2021-08-28 20:45:24 +08:00
echo $status
# CHECK: 0
path change-extension '' ~/.config
Add "path" builtin This adds a "path" builtin that can handle paths. Implemented so far: - "path filter PATHS", filters paths according to existence and optionally type and permissions - "path base" and "path dir", run basename and dirname, respectively - "path extension PATHS", prints the extension, if any - "path strip-extension", prints the path without the extension - "path normalize PATHS", normalizes paths - removing "/./" components - and such. - "path real", does realpath - i.e. normalizing *and* link resolution. Some of these - base, dir, {strip-,}extension and normalize operate on the paths only as strings, so they handle nonexistent paths. filter and real ignore any nonexistent paths. All output is split explicitly, so paths with newlines in them are handled correctly. Alternatively, all subcommands have a "--null-input"/"-z" and "--null-output"/"-Z" option to handle null-terminated input and create null-terminated output. So find . -print0 | path base -z prints the basename of all files in the current directory, recursively. With "-Z" it also prints it null-separated. (if stdout is going to a command substitution, we probably want to skip this) All subcommands also have a "-q"/"--quiet" flag that tells them to skip output. They return true "when something happened". For match/filter that's when a file passed, for "base"/"dir"/"extension"/"strip-extension" that's when something about the path *changed*. Filtering --------- `filter` supports all the file*types* `test` has - "dir", "file", "link", "block"..., as well as the permissions - "read", "write", "exec" and things like "suid". It is missing the tty check and the check for the file being non-empty. The former is best done via `isatty`, the latter I don't think I've ever seen used. There currently is no way to only get "real" files, i.e. ignore links pointing to files. Examples -------- > path real /bin///sh /usr/bin/bash > path extension foo.mp4 mp4 > path extension ~/.config (nothing, because ".config" isn't an extension.)
2021-08-28 20:45:24 +08:00
# CHECK: {{.*}}/.config
echo $status
# CHECK: 0
Add "path" builtin This adds a "path" builtin that can handle paths. Implemented so far: - "path filter PATHS", filters paths according to existence and optionally type and permissions - "path base" and "path dir", run basename and dirname, respectively - "path extension PATHS", prints the extension, if any - "path strip-extension", prints the path without the extension - "path normalize PATHS", normalizes paths - removing "/./" components - and such. - "path real", does realpath - i.e. normalizing *and* link resolution. Some of these - base, dir, {strip-,}extension and normalize operate on the paths only as strings, so they handle nonexistent paths. filter and real ignore any nonexistent paths. All output is split explicitly, so paths with newlines in them are handled correctly. Alternatively, all subcommands have a "--null-input"/"-z" and "--null-output"/"-Z" option to handle null-terminated input and create null-terminated output. So find . -print0 | path base -z prints the basename of all files in the current directory, recursively. With "-Z" it also prints it null-separated. (if stdout is going to a command substitution, we probably want to skip this) All subcommands also have a "-q"/"--quiet" flag that tells them to skip output. They return true "when something happened". For match/filter that's when a file passed, for "base"/"dir"/"extension"/"strip-extension" that's when something about the path *changed*. Filtering --------- `filter` supports all the file*types* `test` has - "dir", "file", "link", "block"..., as well as the permissions - "read", "write", "exec" and things like "suid". It is missing the tty check and the check for the file being non-empty. The former is best done via `isatty`, the latter I don't think I've ever seen used. There currently is no way to only get "real" files, i.e. ignore links pointing to files. Examples -------- > path real /bin///sh /usr/bin/bash > path extension foo.mp4 mp4 > path extension ~/.config (nothing, because ".config" isn't an extension.)
2021-08-28 20:45:24 +08:00
path basename ./foo.mp4
Add "path" builtin This adds a "path" builtin that can handle paths. Implemented so far: - "path filter PATHS", filters paths according to existence and optionally type and permissions - "path base" and "path dir", run basename and dirname, respectively - "path extension PATHS", prints the extension, if any - "path strip-extension", prints the path without the extension - "path normalize PATHS", normalizes paths - removing "/./" components - and such. - "path real", does realpath - i.e. normalizing *and* link resolution. Some of these - base, dir, {strip-,}extension and normalize operate on the paths only as strings, so they handle nonexistent paths. filter and real ignore any nonexistent paths. All output is split explicitly, so paths with newlines in them are handled correctly. Alternatively, all subcommands have a "--null-input"/"-z" and "--null-output"/"-Z" option to handle null-terminated input and create null-terminated output. So find . -print0 | path base -z prints the basename of all files in the current directory, recursively. With "-Z" it also prints it null-separated. (if stdout is going to a command substitution, we probably want to skip this) All subcommands also have a "-q"/"--quiet" flag that tells them to skip output. They return true "when something happened". For match/filter that's when a file passed, for "base"/"dir"/"extension"/"strip-extension" that's when something about the path *changed*. Filtering --------- `filter` supports all the file*types* `test` has - "dir", "file", "link", "block"..., as well as the permissions - "read", "write", "exec" and things like "suid". It is missing the tty check and the check for the file being non-empty. The former is best done via `isatty`, the latter I don't think I've ever seen used. There currently is no way to only get "real" files, i.e. ignore links pointing to files. Examples -------- > path real /bin///sh /usr/bin/bash > path extension foo.mp4 mp4 > path extension ~/.config (nothing, because ".config" isn't an extension.)
2021-08-28 20:45:24 +08:00
# CHECK: foo.mp4
path basename ../banana
Add "path" builtin This adds a "path" builtin that can handle paths. Implemented so far: - "path filter PATHS", filters paths according to existence and optionally type and permissions - "path base" and "path dir", run basename and dirname, respectively - "path extension PATHS", prints the extension, if any - "path strip-extension", prints the path without the extension - "path normalize PATHS", normalizes paths - removing "/./" components - and such. - "path real", does realpath - i.e. normalizing *and* link resolution. Some of these - base, dir, {strip-,}extension and normalize operate on the paths only as strings, so they handle nonexistent paths. filter and real ignore any nonexistent paths. All output is split explicitly, so paths with newlines in them are handled correctly. Alternatively, all subcommands have a "--null-input"/"-z" and "--null-output"/"-Z" option to handle null-terminated input and create null-terminated output. So find . -print0 | path base -z prints the basename of all files in the current directory, recursively. With "-Z" it also prints it null-separated. (if stdout is going to a command substitution, we probably want to skip this) All subcommands also have a "-q"/"--quiet" flag that tells them to skip output. They return true "when something happened". For match/filter that's when a file passed, for "base"/"dir"/"extension"/"strip-extension" that's when something about the path *changed*. Filtering --------- `filter` supports all the file*types* `test` has - "dir", "file", "link", "block"..., as well as the permissions - "read", "write", "exec" and things like "suid". It is missing the tty check and the check for the file being non-empty. The former is best done via `isatty`, the latter I don't think I've ever seen used. There currently is no way to only get "real" files, i.e. ignore links pointing to files. Examples -------- > path real /bin///sh /usr/bin/bash > path extension foo.mp4 mp4 > path extension ~/.config (nothing, because ".config" isn't an extension.)
2021-08-28 20:45:24 +08:00
# CHECK: banana
path basename /usr/bin/
Add "path" builtin This adds a "path" builtin that can handle paths. Implemented so far: - "path filter PATHS", filters paths according to existence and optionally type and permissions - "path base" and "path dir", run basename and dirname, respectively - "path extension PATHS", prints the extension, if any - "path strip-extension", prints the path without the extension - "path normalize PATHS", normalizes paths - removing "/./" components - and such. - "path real", does realpath - i.e. normalizing *and* link resolution. Some of these - base, dir, {strip-,}extension and normalize operate on the paths only as strings, so they handle nonexistent paths. filter and real ignore any nonexistent paths. All output is split explicitly, so paths with newlines in them are handled correctly. Alternatively, all subcommands have a "--null-input"/"-z" and "--null-output"/"-Z" option to handle null-terminated input and create null-terminated output. So find . -print0 | path base -z prints the basename of all files in the current directory, recursively. With "-Z" it also prints it null-separated. (if stdout is going to a command substitution, we probably want to skip this) All subcommands also have a "-q"/"--quiet" flag that tells them to skip output. They return true "when something happened". For match/filter that's when a file passed, for "base"/"dir"/"extension"/"strip-extension" that's when something about the path *changed*. Filtering --------- `filter` supports all the file*types* `test` has - "dir", "file", "link", "block"..., as well as the permissions - "read", "write", "exec" and things like "suid". It is missing the tty check and the check for the file being non-empty. The former is best done via `isatty`, the latter I don't think I've ever seen used. There currently is no way to only get "real" files, i.e. ignore links pointing to files. Examples -------- > path real /bin///sh /usr/bin/bash > path extension foo.mp4 mp4 > path extension ~/.config (nothing, because ".config" isn't an extension.)
2021-08-28 20:45:24 +08:00
# CHECK: bin
path dirname ./foo.mp4
Add "path" builtin This adds a "path" builtin that can handle paths. Implemented so far: - "path filter PATHS", filters paths according to existence and optionally type and permissions - "path base" and "path dir", run basename and dirname, respectively - "path extension PATHS", prints the extension, if any - "path strip-extension", prints the path without the extension - "path normalize PATHS", normalizes paths - removing "/./" components - and such. - "path real", does realpath - i.e. normalizing *and* link resolution. Some of these - base, dir, {strip-,}extension and normalize operate on the paths only as strings, so they handle nonexistent paths. filter and real ignore any nonexistent paths. All output is split explicitly, so paths with newlines in them are handled correctly. Alternatively, all subcommands have a "--null-input"/"-z" and "--null-output"/"-Z" option to handle null-terminated input and create null-terminated output. So find . -print0 | path base -z prints the basename of all files in the current directory, recursively. With "-Z" it also prints it null-separated. (if stdout is going to a command substitution, we probably want to skip this) All subcommands also have a "-q"/"--quiet" flag that tells them to skip output. They return true "when something happened". For match/filter that's when a file passed, for "base"/"dir"/"extension"/"strip-extension" that's when something about the path *changed*. Filtering --------- `filter` supports all the file*types* `test` has - "dir", "file", "link", "block"..., as well as the permissions - "read", "write", "exec" and things like "suid". It is missing the tty check and the check for the file being non-empty. The former is best done via `isatty`, the latter I don't think I've ever seen used. There currently is no way to only get "real" files, i.e. ignore links pointing to files. Examples -------- > path real /bin///sh /usr/bin/bash > path extension foo.mp4 mp4 > path extension ~/.config (nothing, because ".config" isn't an extension.)
2021-08-28 20:45:24 +08:00
# CHECK: .
path basename ../banana
Add "path" builtin This adds a "path" builtin that can handle paths. Implemented so far: - "path filter PATHS", filters paths according to existence and optionally type and permissions - "path base" and "path dir", run basename and dirname, respectively - "path extension PATHS", prints the extension, if any - "path strip-extension", prints the path without the extension - "path normalize PATHS", normalizes paths - removing "/./" components - and such. - "path real", does realpath - i.e. normalizing *and* link resolution. Some of these - base, dir, {strip-,}extension and normalize operate on the paths only as strings, so they handle nonexistent paths. filter and real ignore any nonexistent paths. All output is split explicitly, so paths with newlines in them are handled correctly. Alternatively, all subcommands have a "--null-input"/"-z" and "--null-output"/"-Z" option to handle null-terminated input and create null-terminated output. So find . -print0 | path base -z prints the basename of all files in the current directory, recursively. With "-Z" it also prints it null-separated. (if stdout is going to a command substitution, we probably want to skip this) All subcommands also have a "-q"/"--quiet" flag that tells them to skip output. They return true "when something happened". For match/filter that's when a file passed, for "base"/"dir"/"extension"/"strip-extension" that's when something about the path *changed*. Filtering --------- `filter` supports all the file*types* `test` has - "dir", "file", "link", "block"..., as well as the permissions - "read", "write", "exec" and things like "suid". It is missing the tty check and the check for the file being non-empty. The former is best done via `isatty`, the latter I don't think I've ever seen used. There currently is no way to only get "real" files, i.e. ignore links pointing to files. Examples -------- > path real /bin///sh /usr/bin/bash > path extension foo.mp4 mp4 > path extension ~/.config (nothing, because ".config" isn't an extension.)
2021-08-28 20:45:24 +08:00
# CHECK: banana
path basename /usr/bin/
Add "path" builtin This adds a "path" builtin that can handle paths. Implemented so far: - "path filter PATHS", filters paths according to existence and optionally type and permissions - "path base" and "path dir", run basename and dirname, respectively - "path extension PATHS", prints the extension, if any - "path strip-extension", prints the path without the extension - "path normalize PATHS", normalizes paths - removing "/./" components - and such. - "path real", does realpath - i.e. normalizing *and* link resolution. Some of these - base, dir, {strip-,}extension and normalize operate on the paths only as strings, so they handle nonexistent paths. filter and real ignore any nonexistent paths. All output is split explicitly, so paths with newlines in them are handled correctly. Alternatively, all subcommands have a "--null-input"/"-z" and "--null-output"/"-Z" option to handle null-terminated input and create null-terminated output. So find . -print0 | path base -z prints the basename of all files in the current directory, recursively. With "-Z" it also prints it null-separated. (if stdout is going to a command substitution, we probably want to skip this) All subcommands also have a "-q"/"--quiet" flag that tells them to skip output. They return true "when something happened". For match/filter that's when a file passed, for "base"/"dir"/"extension"/"strip-extension" that's when something about the path *changed*. Filtering --------- `filter` supports all the file*types* `test` has - "dir", "file", "link", "block"..., as well as the permissions - "read", "write", "exec" and things like "suid". It is missing the tty check and the check for the file being non-empty. The former is best done via `isatty`, the latter I don't think I've ever seen used. There currently is no way to only get "real" files, i.e. ignore links pointing to files. Examples -------- > path real /bin///sh /usr/bin/bash > path extension foo.mp4 mp4 > path extension ~/.config (nothing, because ".config" isn't an extension.)
2021-08-28 20:45:24 +08:00
# CHECK: bin
cd $TMPDIR
mkdir -p bin
touch bin/{bash,bssh,chsh,dash,fish,slsh,ssh,zsh}
ln -s $TMPDIR/bin/bash bin/sh
chmod +x bin/*
# We need files from here on
path filter bin argagagji
# The (hopefully) nonexistent argagagji is filtered implicitly:
# CHECK: bin
# With --invert, the existing bin is filtered
path filter --invert bin argagagji
# CHECK: argagagji
# With --invert and a type, bin fails the type,
# and argagagji doesn't exist, so both are printed.
path filter -vf bin argagagji
# CHECK: bin
# CHECK: argagagji
Add "path" builtin This adds a "path" builtin that can handle paths. Implemented so far: - "path filter PATHS", filters paths according to existence and optionally type and permissions - "path base" and "path dir", run basename and dirname, respectively - "path extension PATHS", prints the extension, if any - "path strip-extension", prints the path without the extension - "path normalize PATHS", normalizes paths - removing "/./" components - and such. - "path real", does realpath - i.e. normalizing *and* link resolution. Some of these - base, dir, {strip-,}extension and normalize operate on the paths only as strings, so they handle nonexistent paths. filter and real ignore any nonexistent paths. All output is split explicitly, so paths with newlines in them are handled correctly. Alternatively, all subcommands have a "--null-input"/"-z" and "--null-output"/"-Z" option to handle null-terminated input and create null-terminated output. So find . -print0 | path base -z prints the basename of all files in the current directory, recursively. With "-Z" it also prints it null-separated. (if stdout is going to a command substitution, we probably want to skip this) All subcommands also have a "-q"/"--quiet" flag that tells them to skip output. They return true "when something happened". For match/filter that's when a file passed, for "base"/"dir"/"extension"/"strip-extension" that's when something about the path *changed*. Filtering --------- `filter` supports all the file*types* `test` has - "dir", "file", "link", "block"..., as well as the permissions - "read", "write", "exec" and things like "suid". It is missing the tty check and the check for the file being non-empty. The former is best done via `isatty`, the latter I don't think I've ever seen used. There currently is no way to only get "real" files, i.e. ignore links pointing to files. Examples -------- > path real /bin///sh /usr/bin/bash > path extension foo.mp4 mp4 > path extension ~/.config (nothing, because ".config" isn't an extension.)
2021-08-28 20:45:24 +08:00
path filter --type file bin bin/fish
# Only fish is a file
# CHECK: bin/fish
chmod 500 bin/fish
path filter --type file,dir --perm exec,write bin/fish .
# fish is a file, which passes, and executable, which passes,
# but not writable, which fails.
#
# . is a directory and both writable and executable, typically.
# So it passes.
# CHECK: .
mkdir -p sbin
touch sbin/setuid-exe sbin/setgid-exe
chmod u+s,a+x sbin/setuid-exe
chmod g+s,a+x sbin/setgid-exe
path filter --perm suid sbin/*
# CHECK: sbin/setuid-exe
path filter --perm sgid sbin/*
# CHECK: sbin/setgid-exe
mkdir stuff
touch stuff/{read,write,exec,readwrite,readexec,writeexec,all,none}
chmod 400 stuff/read
chmod 200 stuff/write
chmod 100 stuff/exec
chmod 600 stuff/readwrite
chmod 500 stuff/readexec
chmod 300 stuff/writeexec
chmod 700 stuff/all
chmod 000 stuff/none
path filter --perm read stuff/* | path sort
# CHECK: stuff/all
# CHECK: stuff/read
# CHECK: stuff/readexec
# CHECK: stuff/readwrite
2023-08-07 09:49:04 +08:00
path filter -r stuff/* | path sort
# CHECK: stuff/all
# CHECK: stuff/read
# CHECK: stuff/readexec
# CHECK: stuff/readwrite
path filter --perm write stuff/* | path sort
# CHECK: stuff/all
# CHECK: stuff/readwrite
# CHECK: stuff/write
# CHECK: stuff/writeexec
2023-08-07 09:49:04 +08:00
path filter -w stuff/* | path sort
# CHECK: stuff/all
# CHECK: stuff/readwrite
# CHECK: stuff/write
# CHECK: stuff/writeexec
path filter --perm exec stuff/* | path sort
# CHECK: stuff/all
# CHECK: stuff/exec
# CHECK: stuff/readexec
# CHECK: stuff/writeexec
2023-08-07 09:49:04 +08:00
path filter -x stuff/* | path sort
# CHECK: stuff/all
# CHECK: stuff/exec
# CHECK: stuff/readexec
# CHECK: stuff/writeexec
path filter --perm read,write stuff/* | path sort
# CHECK: stuff/all
# CHECK: stuff/readwrite
path filter --perm read,exec stuff/* | path sort
# CHECK: stuff/all
# CHECK: stuff/readexec
path filter --perm write,exec stuff/* | path sort
# CHECK: stuff/all
# CHECK: stuff/writeexec
path filter --perm read,write,exec stuff/* | path sort
# CHECK: stuff/all
path filter stuff/* | path sort
# CHECK: stuff/all
# CHECK: stuff/exec
# CHECK: stuff/none
# CHECK: stuff/read
# CHECK: stuff/readexec
# CHECK: stuff/readwrite
# CHECK: stuff/write
# CHECK: stuff/writeexec
Add "path" builtin This adds a "path" builtin that can handle paths. Implemented so far: - "path filter PATHS", filters paths according to existence and optionally type and permissions - "path base" and "path dir", run basename and dirname, respectively - "path extension PATHS", prints the extension, if any - "path strip-extension", prints the path without the extension - "path normalize PATHS", normalizes paths - removing "/./" components - and such. - "path real", does realpath - i.e. normalizing *and* link resolution. Some of these - base, dir, {strip-,}extension and normalize operate on the paths only as strings, so they handle nonexistent paths. filter and real ignore any nonexistent paths. All output is split explicitly, so paths with newlines in them are handled correctly. Alternatively, all subcommands have a "--null-input"/"-z" and "--null-output"/"-Z" option to handle null-terminated input and create null-terminated output. So find . -print0 | path base -z prints the basename of all files in the current directory, recursively. With "-Z" it also prints it null-separated. (if stdout is going to a command substitution, we probably want to skip this) All subcommands also have a "-q"/"--quiet" flag that tells them to skip output. They return true "when something happened". For match/filter that's when a file passed, for "base"/"dir"/"extension"/"strip-extension" that's when something about the path *changed*. Filtering --------- `filter` supports all the file*types* `test` has - "dir", "file", "link", "block"..., as well as the permissions - "read", "write", "exec" and things like "suid". It is missing the tty check and the check for the file being non-empty. The former is best done via `isatty`, the latter I don't think I've ever seen used. There currently is no way to only get "real" files, i.e. ignore links pointing to files. Examples -------- > path real /bin///sh /usr/bin/bash > path extension foo.mp4 mp4 > path extension ~/.config (nothing, because ".config" isn't an extension.)
2021-08-28 20:45:24 +08:00
path normalize /usr/bin//../../etc/fish
# The "//" is squashed and the ".." components neutralize the components before
# CHECK: /etc/fish
path normalize /bin//bash
# The "//" is squashed, but /bin isn't resolved even if your system links it to /usr/bin.
# CHECK: /bin/bash
# Paths with "-" get a "./":
path normalize -- -/foo -foo/foo
# CHECK: ./-/foo
# CHECK: ./-foo/foo
path normalize -- ../-foo
# CHECK: ../-foo
# This goes for filter as well
touch -- -foo
path filter -f -- -foo
# CHECK: ./-foo
Add "path" builtin This adds a "path" builtin that can handle paths. Implemented so far: - "path filter PATHS", filters paths according to existence and optionally type and permissions - "path base" and "path dir", run basename and dirname, respectively - "path extension PATHS", prints the extension, if any - "path strip-extension", prints the path without the extension - "path normalize PATHS", normalizes paths - removing "/./" components - and such. - "path real", does realpath - i.e. normalizing *and* link resolution. Some of these - base, dir, {strip-,}extension and normalize operate on the paths only as strings, so they handle nonexistent paths. filter and real ignore any nonexistent paths. All output is split explicitly, so paths with newlines in them are handled correctly. Alternatively, all subcommands have a "--null-input"/"-z" and "--null-output"/"-Z" option to handle null-terminated input and create null-terminated output. So find . -print0 | path base -z prints the basename of all files in the current directory, recursively. With "-Z" it also prints it null-separated. (if stdout is going to a command substitution, we probably want to skip this) All subcommands also have a "-q"/"--quiet" flag that tells them to skip output. They return true "when something happened". For match/filter that's when a file passed, for "base"/"dir"/"extension"/"strip-extension" that's when something about the path *changed*. Filtering --------- `filter` supports all the file*types* `test` has - "dir", "file", "link", "block"..., as well as the permissions - "read", "write", "exec" and things like "suid". It is missing the tty check and the check for the file being non-empty. The former is best done via `isatty`, the latter I don't think I've ever seen used. There currently is no way to only get "real" files, i.e. ignore links pointing to files. Examples -------- > path real /bin///sh /usr/bin/bash > path extension foo.mp4 mp4 > path extension ~/.config (nothing, because ".config" isn't an extension.)
2021-08-28 20:45:24 +08:00
# We need to remove the rest of the path because we have no idea what its value looks like.
2022-01-29 00:22:16 +08:00
path resolve bin//sh | string match -r -- 'bin/bash$'
Add "path" builtin This adds a "path" builtin that can handle paths. Implemented so far: - "path filter PATHS", filters paths according to existence and optionally type and permissions - "path base" and "path dir", run basename and dirname, respectively - "path extension PATHS", prints the extension, if any - "path strip-extension", prints the path without the extension - "path normalize PATHS", normalizes paths - removing "/./" components - and such. - "path real", does realpath - i.e. normalizing *and* link resolution. Some of these - base, dir, {strip-,}extension and normalize operate on the paths only as strings, so they handle nonexistent paths. filter and real ignore any nonexistent paths. All output is split explicitly, so paths with newlines in them are handled correctly. Alternatively, all subcommands have a "--null-input"/"-z" and "--null-output"/"-Z" option to handle null-terminated input and create null-terminated output. So find . -print0 | path base -z prints the basename of all files in the current directory, recursively. With "-Z" it also prints it null-separated. (if stdout is going to a command substitution, we probably want to skip this) All subcommands also have a "-q"/"--quiet" flag that tells them to skip output. They return true "when something happened". For match/filter that's when a file passed, for "base"/"dir"/"extension"/"strip-extension" that's when something about the path *changed*. Filtering --------- `filter` supports all the file*types* `test` has - "dir", "file", "link", "block"..., as well as the permissions - "read", "write", "exec" and things like "suid". It is missing the tty check and the check for the file being non-empty. The former is best done via `isatty`, the latter I don't think I've ever seen used. There currently is no way to only get "real" files, i.e. ignore links pointing to files. Examples -------- > path real /bin///sh /usr/bin/bash > path extension foo.mp4 mp4 > path extension ~/.config (nothing, because ".config" isn't an extension.)
2021-08-28 20:45:24 +08:00
# The "//" is squashed, and the symlink is resolved.
# sh here is bash
# CHECK: bin/bash
# "../" cancels out even files.
path resolve bin//sh/../ | string match -r -- 'bin$'
# CHECK: bin
2022-01-29 00:22:16 +08:00
# `path resolve` with nonexistent paths
set -l path (path resolve foo/bar)
string match -rq "^"(pwd -P | string escape --style=regex)'/' -- $path
and echo It matches pwd!
or echo pwd is \'$PWD\' resolved path is \'$path\'
# CHECK: It matches pwd!
string replace -r "^"(pwd -P | string escape --style=regex)'/' "" -- $path
# CHECK: foo/bar
2022-01-29 00:22:16 +08:00
path resolve /banana//terracota/terracota/booooo/../pie
# CHECK: /banana/terracota/terracota/pie
path sort --key=basename {def,abc}/{456,123,789,abc,def,0} | path sort --key=dirname -r
# CHECK: def/0
# CHECK: def/123
# CHECK: def/456
# CHECK: def/789
# CHECK: def/abc
# CHECK: def/def
# CHECK: abc/0
# CHECK: abc/123
# CHECK: abc/456
# CHECK: abc/789
# CHECK: abc/abc
# CHECK: abc/def
2022-04-27 03:10:54 +08:00
path sort --unique --key=basename {def,abc}/{456,123,789} def/{abc,def,0} abc/{foo,bar,baz}
2022-04-27 03:10:54 +08:00
# CHECK: def/0
# CHECK: def/123
# CHECK: def/456
# CHECK: def/789
# CHECK: def/abc
# CHECK: abc/bar
# CHECK: abc/baz
# CHECK: def/def
# CHECK: abc/foo
2022-05-20 03:08:11 +08:00
# Symlink loop.
# It goes brrr.
ln -s target link
ln -s link target
test (path resolve target) = (pwd -P)/target
and echo target resolves to target
# CHECK: target resolves to target
test (path resolve link) = (pwd -P)/link
and echo link resolves to link
# CHECK: link resolves to link
# path mtime
# These tests deal with *time*, so we have to account
# for slow systems (like CI).
# So we should only test with a lot of slack.
echo bananana >> foo
test (math abs (date +%s) - (path mtime foo)) -lt 20
or echo MTIME IS BOGUS
sleep 2
set -l mtime (path mtime --relative foo)
test $mtime -ge 1
or echo mtime is too small
test $mtime -lt 20
or echo mtime is too large
touch -m -t 197001020000 epoch
set -l epochtime (path mtime epoch)
# Allow for timezone shenanigans
test $epochtime -gt 0 -a $epochtime -lt 180000
or echo Oops not mtime
path basename -Z foo bar baz | path sort
# CHECK: bar
# CHECK: baz
# CHECK: foo
path basename --null-out bar baz | string escape
# CHECK: bar\x00baz\x00