Files

490 lines
12 KiB
Fish
Raw Permalink Normal View History

#RUN: %fish %s
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 14:45:24 +02:00
# The "path" builtin for dealing with paths
cygwin_nosymlinks && set nosymlinks
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 14:45:24 +02:00
# 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 14:45:24 +02: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 14:45:24 +02: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 14:45:24 +02: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 14:45:24 +02: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 14:45:24 +02: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 14:45:24 +02: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 14:45:24 +02: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 14:45:24 +02: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 14:45:24 +02: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 14:45:24 +02: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 14:45:24 +02: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 14:45:24 +02: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 14:45:24 +02: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 14:45:24 +02: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 14:45:24 +02: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 14:45:24 +02: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 14:45:24 +02: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 14:45:24 +02: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 14:45:24 +02: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 14:45:24 +02: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 14:45:24 +02: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 14:45:24 +02: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 14:45:24 +02:00
# CHECK: bin
cd $TMPDIR
cygwin_noacl ./ && set -l noacl
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 14:45:24 +02:00
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
# With --all, return true if all paths are passed.
path filter --all bin bin/bash
echo $status
# CHECK: 0
path filter --all bin argagagji
echo $status
# CHECK: 1
# With --all and --invert, return true if none of paths is passed.
path filter --all --invert bin bin/bash
echo $status
# CHECK: 1
path filter --all --invert argagagji argagagji2
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 14:45:24 +02: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
# Without POSIX permission, there is no way to set the setuid bit, so fake
# the output.
if set -q noacl
echo sbin/setuid-exe
else
chmod u+s,a+x sbin/setuid-exe
path filter --perm suid sbin/*
end
# CHECK: sbin/setuid-exe
2023-08-07 17:21:07 +02:00
# Without POSIX permission, there is no way to set the setgid bit, so fake
# the result.
# And on at least FreeBSD on our CI this fails with "permission denied".
# So we can't test it, and we fake the output there too.
if set -q noacl
echo sbin/setgid-exe
else if chmod g+s,a+x sbin/setgid-exe 2>/dev/null
2023-08-07 17:21:07 +02:00
path filter --perm sgid sbin/*
else
echo sbin/setgid-exe
end
# CHECK: sbin/setgid-exe
mkdir stuff
touch stuff/{read,write,exec,readwrite,readexec,writeexec,all,none}
if set -q noacl
echo "#!/bin/sh" >stuff/exec
echo "#!/bin/sh" >stuff/readexec
echo "#!/bin/sh" >stuff/writeexec
echo "#!/bin/sh" >stuff/all
end
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
# Validate that globs are sorted.
test (path filter stuff/* | path sort | string join ",") = (path filter stuff/* | string join ",")
# echo/CHECK to separate the output of different tests since they all blend
# together otherwise, making it hard to know which test failed.
echo "=== test --perm read"
# CHECK: === test --perm read
if set -q noacl
# noacl cannot mark files non-readable, filter out known bad files
path filter --perm read stuff/* | string match -rv ".*/(?:write|exec|writeexec|none).*"
else
path filter --perm read stuff/*
end
# CHECK: stuff/all
# CHECK: stuff/read
# CHECK: stuff/readexec
# CHECK: stuff/readwrite
echo "=== test -r"
# CHECK: === test -r
if set -q noacl
path filter -r stuff/* | string match -rv ".*/(?:write|exec|writeexec|none).*"
else
path filter -r stuff/*
end
2023-08-06 18:49:04 -07:00
# CHECK: stuff/all
# CHECK: stuff/read
# CHECK: stuff/readexec
# CHECK: stuff/readwrite
echo "=== test --perm write"
# CHECK: === test --perm write
path filter --perm write stuff/*
# CHECK: stuff/all
# CHECK: stuff/readwrite
# CHECK: stuff/write
# CHECK: stuff/writeexec
echo "=== test -w"
# CHECK: === test -w
path filter -w stuff/*
2023-08-06 18:49:04 -07:00
# CHECK: stuff/all
# CHECK: stuff/readwrite
# CHECK: stuff/write
# CHECK: stuff/writeexec
echo "=== test --perm exec"
# CHECK: === test --perm exec
begin
path filter --perm exec stuff/*
# Cygwin with ACL doesn't return non-readable files, so add them manually to pass the test
if __fish_is_cygwin && ! set -q noacl
echo stuff/exec
echo stuff/writeexec
end
end | sort
# CHECK: stuff/all
# CHECK: stuff/exec
# CHECK: stuff/readexec
# CHECK: stuff/writeexec
echo "=== test -x"
# CHECK: === test -x
begin
path filter -x exec stuff/*
if __fish_is_cygwin && ! set -q noacl
echo stuff/exec
echo stuff/writeexec
end
end | sort
2023-08-06 18:49:04 -07:00
# CHECK: stuff/all
# CHECK: stuff/exec
# CHECK: stuff/readexec
# CHECK: stuff/writeexec
echo "=== test --perm read,write"
# CHECK: === test --perm read,write
if set -q noacl
path filter --perm read,write stuff/* | string match -rv ".*/(?:write|writeexec).*"
else
path filter --perm read,write stuff/*
end
# CHECK: stuff/all
# CHECK: stuff/readwrite
echo "=== test --perm read,exec"
# CHECK: === test --perm read,exec
if set -q noacl
path filter --perm read,exec stuff/* | string match -rv ".*/(?:exec|writeexec).*"
else
path filter --perm read,exec stuff/*
end
# CHECK: stuff/all
# CHECK: stuff/readexec
echo "=== test --perm write,exec"
# CHECK: === test --perm write,exec
begin
path filter --perm write,exec stuff/*
if __fish_is_cygwin && ! set -q noacl
echo stuff/writeexec
end
end | sort
# CHECK: stuff/all
# CHECK: stuff/writeexec
echo "=== test --perm read,write,exec"
# CHECK: === test --perm read,write,exec
if set -q noacl
path filter --perm read,write,exec stuff/* | string match -rv ".*/(?:writeexec).*"
else
path filter --perm read,write,exec stuff/*
end
# CHECK: stuff/all
echo "=== test all"
# CHECK: === test all
path filter stuff/*
# 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 14:45:24 +02: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 14:45:24 +02:00
# We need to remove the rest of the path because we have no idea what its value looks like.
if set -q nosymlinks
echo bin/bash
else
path resolve bin//sh | string match -r -- 'bin/bash$'
end
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 14:45:24 +02: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-28 17:22:16 +01: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-28 17:22:16 +01: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-26 21:10:54 +02:00
path sort --unique --key=basename {def,abc}/{456,123,789} def/{abc,def,0} abc/{foo,bar,baz}
2022-04-26 21:10:54 +02: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-19 21:08:11 +02:00
# Symlink loop.
# It goes brrr.
if not set -q nosymlinks
ln -s target link
ln -s link target
end
2022-05-19 21:08:11 +02:00
if set -q nosymlinks ||
test (path resolve target) = (pwd -P)/target
echo target resolves to target
end
2022-05-19 21:08:11 +02:00
# CHECK: target resolves to target
if set -q nosymlinks ||
test (path resolve link) = (pwd -P)/link
echo link resolves to link
end
2022-05-19 21:08:11 +02:00
# 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
2024-05-24 18:03:42 -05:00
path basename -E foo.txt /usr/local/foo.bar /foo.tar.gz
# CHECK: foo
# CHECK: foo
# CHECK: foo.tar
path basename --null-out bar baz | string escape
# CHECK: bar\x00baz\x00
path basename --quiet=foo
# CHECKERR: path basename: --quiet=foo: option does not take an argument
path basename --unknown-option
# CHECKERR: path basename: --unknown-option: unknown option
# CHECKERR: {{.*}}/checks/path.fish (line {{\d+}}):
# CHECKERR: path basename --unknown-option
# CHECKERR: ^
# CHECKERR: (Type 'help path' for related documentation)
path filter -t invalid_type
# CHECKERR: path filter: Invalid type 'invalid_type'
path filter -p 999
# CHECKERR: path filter: Invalid permission '999'
path sort --relative
# CHECKERR: path sort: --relative: unknown option
# CHECKERR: {{.*}}/checks/path.fish (line {{\d+}}):
# CHECKERR: path sort --relative
# CHECKERR: ^
# CHECKERR: (Type 'help path' for related documentation)
path change-extension
# CHECKERR: path change-extension: missing argument
echo some.file | path basename other.file
# CHECKERR: path basename: too many arguments
path sort --key=invalid-key
# CHECKERR: path sort: Invalid sort key 'invalid-key'
path
# CHECKERR: path: missing subcommand
# CHECKERR: {{.*}}/checks/path.fish (line {{\d+}}):
# CHECKERR: path
# CHECKERR: ^
# CHECKERR: (Type 'help path' for related documentation)
path invalid-subcmd
# CHECKERR: path invalid-subcmd: invalid subcommand
# CHECKERR: {{.*}}/checks/path.fish (line {{\d+}}):
# CHECKERR: path invalid-subcmd
# CHECKERR: ^
# CHECKERR: (Type 'help path' for related documentation)