Repository: clap-rs/clap (language: rust)

Issue:
clap_complete bash: filenames with spaces are not completed properly
### Please complete the following tasks

- [X] I have searched the [discussions](https://github.com/clap-rs/clap/discussions)
- [X] I have searched the [open](https://github.com/clap-rs/clap/issues) and [rejected](https://github.com/clap-rs/clap/issues?q=is%3Aissue+label%3AS-wont-fix+is%3Aclosed) issues

### Rust Version

1.75.0

### Clap Version

clap_complete: 4.4.7

### Minimal reproducible code

Use clap_complete bash completions for an arg that could receive a filename.

### Steps to reproduce the bug with the above code

Create directory with files, one of which has spaces in the name.
```
$ ls
'foo bar.txt'   qux.txt
```

Try to complete `fo` the unique start of one filename.

```
$ ab-av1 encode -i fo<TAB>
```


### Actual Behaviour

Cannot complete.

```
$ ab-av1 encode -i fo
foo      bar.txt
```

### Expected Behaviour

Should be able to complete handling the spaces in the file. E.g. as `ls` completions do: `ls fo<TAB>` -> `ls foo\ bar.txt`.

So I would expect:
`$ ab-av1 encode -i fo<TAB>` -> `$ ab-av1 encode -i foo\ bar.txt`

### Additional Context

Downstream: https://github.com/alexheretic/ab-av1/issues/180

<details>

<summary>Generated bash completion for ab-av1</summary>

```bash
_ab-av1() {
    local i cur prev opts cmd
    COMPREPLY=()
    cur="${COMP_WORDS[COMP_CWORD]}"
    prev="${COMP_WORDS[COMP_CWORD-1]}"
    cmd=""
    opts=""

    for i in ${COMP_WORDS[@]}
    do
        case "${cmd},${i}" in
            ",$1")
                cmd="ab__av1"
                ;;
            ab__av1,auto-encode)
                cmd="ab__av1__auto__encode"
                ;;
            ab__av1,crf-search)
                cmd="ab__av1__crf__search"
                ;;
            ab__av1,encode)
                cmd="ab__av1__encode"
                ;;
            ab__av1,help)
                cmd="ab__av1__help"
                ;;
            ab__av1,print-completions)
                cmd="ab__av1__print__completions"
                ;;
            ab__av1,sample-encode)
                cmd="ab__av1__sample__encode"
                ;;
            ab__av1,vmaf)
                cmd="ab__av1__vmaf"
                ;;
            ab__av1__help,auto-encode)
                cmd="ab__av1__help__auto__encode"
                ;;
            ab__av1__help,crf-search)
                cmd="ab__av1__help__crf__search"
                ;;
            ab__av1__help,encode)
                cmd="ab__av1__help__encode"
                ;;
            ab__av1__help,help)
                cmd="ab__av1__help__help"
                ;;
            ab__av1__help,print-completions)
                cmd="ab__av1__help__print__completions"
                ;;
            ab__av1__help,sample-encode)
                cmd="ab__av1__help__sample__encode"
                ;;
            ab__av1__help,vmaf)
                cmd="ab__av1__help__vmaf"
                ;;
            *)
                ;;
        esac
    done

    case "${cmd}" in
        ab__av1)
            opts="-h -V --help --version sample-encode vmaf encode crf-search auto-encode print-completions help"
            if [[ ${cur} == -* || ${COMP_CWORD} -eq 1 ]] ; then
                COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
                return 0
            fi
            case "${prev}" in
                *)
                    COMPREPLY=()
                    ;;
            esac
            COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
            return 0
            ;;
        ab__av1__auto__encode)
            opts="-e -i -o -h --encoder --input --vfilter --pix-format --preset --keyint --scd --svt --enc --enc-input --min-vmaf --max-encoded-percent --min-crf --max-crf --thorough --crf-increment --cache --samples --sample-every --min-samples --temp-dir --vmaf --vmaf-scale --output --acodec --downmix-to-stereo --video-only --help"
            if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
                COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
                return 0
            fi
            case "${prev}" in
                --encoder)
                    COMPREPLY=($(compgen -f "${cur}"))
                    return 0
                    ;;
                -e)
                    COMPREPLY=($(compgen -f "${cur}"))
                    return 0
                    ;;
                --input)
                    COMPREPLY=($(compgen -f "${cur}"))
                    return 0
                    ;;
                -i)
                    COMPREPLY=($(compgen -f "${cur}"))
                    return 0
                    ;;
                --vfilter)
                    COMPREPLY=($(compgen -f "${cur}"))
                    return 0
                    ;;
                --pix-format)
                    COMPREPLY=($(compgen -W "yuv420p yuv420p10le yuv444p10le" -- "${cur}"))
                    return 0
                    ;;
                --preset)
                    COMPREPLY=($(compgen -f "${cur}"))
                    return 0
                    ;;
                --keyint)
                    COMPREPLY=($(compgen -f "${cur}"))
                    return 0
                    ;;
                --scd)
                    COMPREPLY=($(compgen -W "true false" -- "${cur}"))
                    return 0
                    ;;
                --svt)
                    COMPREPLY=($(compgen -f "${cur}"))
                    return 0
                    ;;
                --enc)
                    COMPREPLY=($(compgen -f "${cur}"))
                    return 0
                    ;;
                --enc-input)
                    COMPREPLY=($(compgen -f "${cur}"))
                    return 0
                    ;;
                --min-vmaf)
                    COMPREPLY=($(compgen -f "${cur}"))
                    return 0
                    ;;
                --max-encoded-percent)
                    COMPREPLY=($(compgen -f "${cur}"))
                    return 0
                    ;;
                --min-crf)
                    COMPREPLY=($(compgen -f "${cur}"))
                    return 0
                    ;;
                --max-crf)
                    COMPREPLY=($(compgen -f "${cur}"))
                    return 0
                    ;;
                --crf-increment)
                    COMPREPLY=($(compgen -f "${cur}"))
                    return 0
                    ;;
                --cache)
                    COMPREPLY=($(compgen -W "true false" -- "${cur}"))
                    return 0
                    ;;
                --samples)
                    COMPREPLY=($(compgen -f "${cur}"))
                    return 0
                    ;;
                --sample-every)
                    COMPREPLY=($(compgen -f "${cur}"))
                    return 0
                    ;;
                --min-samples)
                    COMPREPLY=($(compgen -f "${cur}"))
                    return 0
                    ;;
                --temp-dir)
                    COMPREPLY=($(compgen -f "${cur}"))
                    return 0
                    ;;
                --vmaf)
                    COMPREPLY=($(compgen -f "${cur}"))
                    return 0
                    ;;
                --vmaf-scale)
                    COMPREPLY=($(compgen -f "${cur}"))
                    return 0
                    ;;
                --output)
                    COMPREPLY=($(compgen -f "${cur}"))
                    return 0
                    ;;
                -o)
                    COMPREPLY=($(compgen -f "${cur}"))
                    return 0
                    ;;
                --acodec)
                    COMPREPLY=($(compgen -f "${cur}"))
                    return 0
                    ;;
                *)
                    COMPREPLY=()
                    ;;
            esac
            COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
            return 0
            ;;
        ab__av1__crf__search)
            opts="-e -i -h --encoder --input --vfilter --pix-format --preset --keyint --scd --svt --enc --enc-input --min-vmaf --max-encoded-percent --min-crf --max-crf --thorough --crf-increment --cache --samples --sample-every --min-samples --temp-dir --vmaf --vmaf-scale --help"
            if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
                COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
                return 0
            fi
            case "${prev}" in
                --encoder)
                    COMPREPLY=($(compgen -f "${cur}"))
                    return 0
                    ;;
                -e)
                    COMPREPLY=($(compgen -f "${cur}"))
                    return 0
                    ;;
                --input)
                    COMPREPLY=($(compgen -f "${cur}"))
                    return 0
                    ;;
                -i)
                    COMPREPLY=($(compgen -f "${cur}"))
                    return 0
                    ;;
                --vfilter)
                    COMPREPLY=($(compgen -f "${cur}"))
                    return 0
                    ;;
                --pix-format)
                    COMPREPLY=($(compgen -W "yuv420p yuv420p10le yuv444p10le" -- "${cur}"))
                    return 0
                    ;;
                --preset)
                    COMPREPLY=($(compgen -f "${cur}"))
                    return 0
                    ;;
                --keyint)
                    COMPREPLY=($(compgen -f "${cur}"))
                    return 0
                    ;;
                --scd)
                    COMPREPLY=($(compgen -W "true false" -- "${cur}"))
                    return 0
                    ;;
                --svt)
                    COMPREPLY=($(compgen -f "${cur}"))
                    return 0
                    ;;
                --enc)
                    COMPREPLY=($(compgen -f "${cur}"))
                    return 0
                    ;;
                --enc-input)
                    COMPREPLY=($(compgen -f "${cur}"))
                    return 0
                    ;;
                --min-vmaf)
                    COMPREPLY=($(compgen -f "${cur}"))
                    return 0
                    ;;
                --max-encoded-percent)
                    COMPREPLY=($(compgen -f "${cur}"))
                    return 0
                    ;;
                --min-crf)
                    COMPREPLY=($(compgen -f "${cur}"))
                    return 0
                    ;;
                --max-crf)
                    COMPREPLY=($(compgen -f "${cur}"))
                    return 0
                    ;;
                --crf-increment)
                    COMPREPLY=($(compgen -f "${cur}"))
                    return 0
                    ;;
                --cache)
                    COMPREPLY=($(compgen -W "true false" -- "${cur}"))
                    return 0
                    ;;
                --samples)
                    COMPREPLY=($(compgen -f "${cur}"))
                    return 0
                    ;;
                --sample-every)
                    COMPREPLY=($(compgen -f "${cur}"))
                    return 0
                    ;;
                --min-samples)
                    COMPREPLY=($(compgen -f "${cur}"))
                    return 0
                    ;;
                --temp-dir)
                    COMPREPLY=($(compgen -f "${cur}"))
                    return 0
                    ;;
                --vmaf)
                    COMPREPLY=($(compgen -f "${cur}"))
                    return 0
                    ;;
                --vmaf-scale)
                    COMPREPLY=($(compgen -f "${cur}"))
                    return 0
                    ;;
                *)
                    COMPREPLY=()
                    ;;
            esac
            COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
            return 0
            ;;
        ab__av1__encode)
            opts="-e -i -o -h --encoder --input --vfilter --pix-format --preset --keyint --scd --svt --enc --enc-input --crf --output --acodec --downmix-to-stereo --video-only --help"
            if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
                COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
                return 0
            fi
            case "${prev}" in
                --encoder)
                    COMPREPLY=($(compgen -f "${cur}"))
                    return 0
                    ;;
                -e)
                    COMPREPLY=($(compgen -f "${cur}"))
                    return 0
                    ;;
                --input)
                    COMPREPLY=($(compgen -f "${cur}"))
                    return 0
                    ;;
                -i)
                    COMPREPLY=($(compgen -f "${cur}"))
                    return 0
                    ;;
                --vfilter)
                    COMPREPLY=($(compgen -f "${cur}"))
                    return 0
                    ;;
                --pix-format)
                    COMPREPLY=($(compgen -W "yuv420p yuv420p10le yuv444p10le" -- "${cur}"))
                    return 0
                    ;;
                --preset)
                    COMPREPLY=($(compgen -f "${cur}"))
                    return 0
                    ;;
                --keyint)
                    COMPREPLY=($(compgen -f "${cur}"))
                    return 0
                    ;;
                --scd)
                    COMPREPLY=($(compgen -W "true false" -- "${cur}"))
                    return 0
                    ;;
                --svt)
                    COMPREPLY=($(compgen -f "${cur}"))
                    return 0
                    ;;
                --enc)
                    COMPREPLY=($(compgen -f "${cur}"))
                    return 0
                    ;;
                --enc-input)
                    COMPREPLY=($(compgen -f "${cur}"))
                    return 0
                    ;;
                --crf)
                    COMPREPLY=($(compgen -f "${cur}"))
                    return 0
                    ;;
                --output)
                    COMPREPLY=($(compgen -f "${cur}"))
                    return 0
                    ;;
                -o)
                    COMPREPLY=($(compgen -f "${cur}"))
                    return 0
                    ;;
                --acodec)
                    COMPREPLY=($(compgen -f "${cur}"))
                    return 0
                    ;;
                *)
                    COMPREPLY=()
                    ;;
            esac
            COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
            return 0
            ;;
        ab__av1__help)
            opts="sample-encode vmaf encode crf-search auto-encode print-completions help"
            if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
                COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
                return 0
            fi
            case "${prev}" in
                *)
                    COMPREPLY=()
                    ;;
            esac
            COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
            return 0
            ;;
        ab__av1__help__auto__encode)
            opts=""
            if [[ ${cur} == -* || ${COMP_CWORD} -eq 3 ]] ; then
                COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
                return 0
            fi
            case "${prev}" in
                *)
                    COMPREPLY=()
                    ;;
            esac
            COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
            return 0
            ;;
        ab__av1__help__crf__search)
            opts=""
            if [[ ${cur} == -* || ${COMP_CWORD} -eq 3 ]] ; then
                COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
                return 0
            fi
            case "${prev}" in
                *)
                    COMPREPLY=()
                    ;;
            esac
            COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
            return 0
            ;;
        ab__av1__help__encode)
            opts=""
            if [[ ${cur} == -* || ${COMP_CWORD} -eq 3 ]] ; then
                COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
                return 0
            fi
            case "${prev}" in
                *)
                    COMPREPLY=()
                    ;;
            esac
            COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
            return 0
            ;;
        ab__av1__help__help)
            opts=""
            if [[ ${cur} == -* || ${COMP_CWORD} -eq 3 ]] ; then
                COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
                return 0
            fi
            case "${prev}" in
                *)
                    COMPREPLY=()
                    ;;
            esac
            COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
            return 0
            ;;
        ab__av1__help__print__completions)
            opts=""
            if [[ ${cur} == -* || ${COMP_CWORD} -eq 3 ]] ; then
                COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
                return 0
            fi
            case "${prev}" in
                *)
                    COMPREPLY=()
                    ;;
            esac
            COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
            return 0
            ;;
        ab__av1__help__sample__encode)
            opts=""
            if [[ ${cur} == -* || ${COMP_CWORD} -eq 3 ]] ; then
                COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
                return 0
            fi
            case "${prev}" in
                *)
                    COMPREPLY=()
                    ;;
            esac
            COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
            return 0
            ;;
        ab__av1__help__vmaf)
            opts=""
            if [[ ${cur} == -* || ${COMP_CWORD} -eq 3 ]] ; then
                COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
                return 0
            fi
            case "${prev}" in
                *)
                    COMPREPLY=()
                    ;;
            esac
            COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
            return 0
            ;;
        ab__av1__print__completions)
            opts="-h --help bash elvish fish powershell zsh"
            if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
                COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
                return 0
            fi
            case "${prev}" in
                *)
                    COMPREPLY=()
                    ;;
            esac
            COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
            return 0
            ;;
        ab__av1__sample__encode)
            opts="-e -i -h --encoder --input --vfilter --pix-format --preset --keyint --scd --svt --enc --enc-input --crf --samples --sample-every --min-samples --temp-dir --keep --cache --stdout-format --vmaf --vmaf-scale --help"
            if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
                COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
                return 0
            fi
            case "${prev}" in
                --encoder)
                    COMPREPLY=($(compgen -f "${cur}"))
                    return 0
                    ;;
                -e)
                    COMPREPLY=($(compgen -f "${cur}"))
                    return 0
                    ;;
                --input)
                    COMPREPLY=($(compgen -f "${cur}"))
                    return 0
                    ;;
                -i)
                    COMPREPLY=($(compgen -f "${cur}"))
                    return 0
                    ;;
                --vfilter)
                    COMPREPLY=($(compgen -f "${cur}"))
                    return 0
                    ;;
                --pix-format)
                    COMPREPLY=($(compgen -W "yuv420p yuv420p10le yuv444p10le" -- "${cur}"))
                    return 0
                    ;;
                --preset)
                    COMPREPLY=($(compgen -f "${cur}"))
                    return 0
                    ;;
                --keyint)
                    COMPREPLY=($(compgen -f "${cur}"))
                    return 0
                    ;;
                --scd)
                    COMPREPLY=($(compgen -W "true false" -- "${cur}"))
                    return 0
                    ;;
                --svt)
                    COMPREPLY=($(compgen -f "${cur}"))
                    return 0
                    ;;
                --enc)
                    COMPREPLY=($(compgen -f "${cur}"))
                    return 0
                    ;;
                --enc-input)
                    COMPREPLY=($(compgen -f "${cur}"))
                    return 0
                    ;;
                --crf)
                    COMPREPLY=($(compgen -f "${cur}"))
                    return 0
                    ;;
                --samples)
                    COMPREPLY=($(compgen -f "${cur}"))
                    return 0
                    ;;
                --sample-every)
                    COMPREPLY=($(compgen -f "${cur}"))
                    return 0
                    ;;
                --min-samples)
                    COMPREPLY=($(compgen -f "${cur}"))
                    return 0
                    ;;
                --temp-dir)
                    COMPREPLY=($(compgen -f "${cur}"))
                    return 0
                    ;;
                --cache)
                    COMPREPLY=($(compgen -W "true false" -- "${cur}"))
                    return 0
                    ;;
                --stdout-format)
                    COMPREPLY=($(compgen -W "human json" -- "${cur}"))
                    return 0
                    ;;
                --vmaf)
                    COMPREPLY=($(compgen -f "${cur}"))
                    return 0
                    ;;
                --vmaf-scale)
                    COMPREPLY=($(compgen -f "${cur}"))
                    return 0
                    ;;
                *)
                    COMPREPLY=()
                    ;;
            esac
            COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
            return 0
            ;;
        ab__av1__vmaf)
            opts="-h --reference --reference-vfilter --distorted --vmaf --vmaf-scale --help"
            if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
                COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
                return 0
            fi
            case "${prev}" in
                --reference)
                    COMPREPLY=($(compgen -f "${cur}"))
                    return 0
                    ;;
                --reference-vfilter)
                    COMPREPLY=($(compgen -f "${cur}"))
                    return 0
                    ;;
                --distorted)
                    COMPREPLY=($(compgen -f "${cur}"))
                    return 0
                    ;;
                --vmaf)
                    COMPREPLY=($(compgen -f "${cur}"))
                    return 0
                    ;;
                --vmaf-scale)
                    COMPREPLY=($(compgen -f "${cur}"))
                    return 0
                    ;;
                *)
                    COMPREPLY=()
                    ;;
            esac
            COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
            return 0
            ;;
    esac
}

if [[ "${BASH_VERSINFO[0]}" -eq 4 && "${BASH_VERSINFO[1]}" -ge 4 || "${BASH_VERSINFO[0]}" -gt 4 ]]; then
    complete -F _ab-av1 -o nosort -o bashdefault -o default ab-av1
else
    complete -F _ab-av1 -o bashdefault -o default ab-av1
fi

```

</details>


### Debug Output

_No response_


Discussion / hints:
I wonder if #5240 will fix it.
Maybe we should drop `-f` option from `compgen -f`.

@alexheretic 

Could you try the following patch to the generated completion script, and see if it works as expected?

```diff
@@ -323,10 +323,12 @@
                     return 0
                     ;;
                 --input)
-                    COMPREPLY=($(compgen -f "${cur}"))
+                    COMPREPLY=($(compgen "${cur}"))
+                    compopt -o filenames
                     return 0
                     ;;
                 -i)
-                    COMPREPLY=($(compgen -f "${cur}"))
+                    COMPREPLY=($(compgen "${cur}"))
+                    compopt -o filenames
                     return 0
                     ;;
                 --vfilter)
```

---

If you just try #5240, please apply the following:

```diff
@@ -323,10 +323,12 @@
                     ;;
                 --input)
                     COMPREPLY=($(compgen -f "${cur}"))
+                    compopt -o filenames
                     return 0
                     ;;
                 -i)
                     COMPREPLY=($(compgen -f "${cur}"))
+                    compopt -o filenames
                     return 0
                     ;;
                 --vfilter)

```

Edit: Fixed context line, and append the example of #5240.
@sudotac that change doesn't seem to make any difference
Sorry, I misunderstood the usage. Actually `-o filenames` should be used with `compgen -f`.
However, even if we do so, it doesn't seem to work anyway.
FWIW if you can install bash-completion package (mostly Debian-based systems), it is possible to use `_filedir` for better filename completions.
(it is not a portable solution though)

```diff
@@ -322,11 +322,11 @@
                     return 0
                     ;;
                 --input)
-                    COMPREPLY=($(compgen -f "${cur}"))
+                    _filedir
                     return 0
                     ;;
                 -i)
-                    COMPREPLY=($(compgen -f "${cur}"))
+                    _filedir
                     return 0
                     ;;
                 --vfilter)
```

Fix patch:
diff --git a/clap_complete/src/shells/bash.rs b/clap_complete/src/shells/bash.rs
index f390853a159..5fb39f4b965 100644
--- a/clap_complete/src/shells/bash.rs
+++ b/clap_complete/src/shells/bash.rs
@@ -178,10 +178,23 @@ fn option_details_for_path(cmd: &Command, path: &str) -> String {
 
         if let Some(longs) = o.get_long_and_visible_aliases() {
             opts.extend(longs.iter().map(|long| {
-                let mut v = vec![
-                    format!("--{})", long),
-                    format!("COMPREPLY=({})", vals_for(o)),
-                ];
+                let mut v = vec![format!("--{})", long)];
+
+                if o.get_value_hint() == ValueHint::FilePath {
+                    v.extend([
+                        "local oldifs".to_string(),
+                        "if [[ -v IFS ]]; then".to_string(),
+                        r#"    oldifs="$IFS""#.to_string(),
+                        "fi".to_string(),
+                        r#"IFS=$'\n'"#.to_string(),
+                        format!("COMPREPLY=({})", vals_for(o)),
+                        "if [[ -v oldifs ]]; then".to_string(),
+                        r#"    IFS="$oldifs""#.to_string(),
+                        "fi".to_string(),
+                    ]);
+                } else {
+                    v.push(format!("COMPREPLY=({})", vals_for(o)));
+                }
 
                 if let Some(copt) = compopt {
                     v.extend([
@@ -198,10 +211,23 @@ fn option_details_for_path(cmd: &Command, path: &str) -> String {
 
         if let Some(shorts) = o.get_short_and_visible_aliases() {
             opts.extend(shorts.iter().map(|short| {
-                let mut v = vec![
-                    format!("-{})", short),
-                    format!("COMPREPLY=({})", vals_for(o)),
-                ];
+                let mut v = vec![format!("-{})", short)];
+
+                if o.get_value_hint() == ValueHint::FilePath {
+                    v.extend([
+                        "local oldifs".to_string(),
+                        "if [[ -v IFS ]]; then".to_string(),
+                        r#"    oldifs="$IFS""#.to_string(),
+                        "fi".to_string(),
+                        r#"IFS=$'\n'"#.to_string(),
+                        format!("COMPREPLY=({})", vals_for(o)),
+                        "if [[ -v oldifs ]]; then".to_string(),
+                        r#"    IFS="$oldifs""#.to_string(),
+                        "fi".to_string(),
+                    ]);
+                } else {
+                    v.push(format!("COMPREPLY=({})", vals_for(o)));
+                }
 
                 if let Some(copt) = compopt {
                     v.extend([


Test patch:
diff --git a/clap_complete/tests/snapshots/home/static/exhaustive/bash/.bashrc b/clap_complete/tests/snapshots/home/static/exhaustive/bash/.bashrc
index 2f72ccf40b2..a004f9148fe 100644
--- a/clap_complete/tests/snapshots/home/static/exhaustive/bash/.bashrc
+++ b/clap_complete/tests/snapshots/home/static/exhaustive/bash/.bashrc
@@ -556,14 +556,30 @@ _exhaustive() {
                     return 0
                     ;;
                 --file)
+                    local oldifs
+                    if [[ -v IFS ]]; then
+                        oldifs="$IFS"
+                    fi
+                    IFS=$'\n'
                     COMPREPLY=($(compgen -f "${cur}"))
+                    if [[ -v oldifs ]]; then
+                        IFS="$oldifs"
+                    fi
                     if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then
                         compopt -o filenames
                     fi
                     return 0
                     ;;
                 -f)
+                    local oldifs
+                    if [[ -v IFS ]]; then
+                        oldifs="$IFS"
+                    fi
+                    IFS=$'\n'
                     COMPREPLY=($(compgen -f "${cur}"))
+                    if [[ -v oldifs ]]; then
+                        IFS="$oldifs"
+                    fi
                     if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then
                         compopt -o filenames
                     fi
diff --git a/clap_complete/tests/snapshots/value_hint.bash b/clap_complete/tests/snapshots/value_hint.bash
index 35f6b3d56b1..e2a7f9efd37 100644
--- a/clap_complete/tests/snapshots/value_hint.bash
+++ b/clap_complete/tests/snapshots/value_hint.bash
@@ -49,14 +49,30 @@ _my-app() {
                     return 0
                     ;;
                 --file)
+                    local oldifs
+                    if [[ -v IFS ]]; then
+                        oldifs="$IFS"
+                    fi
+                    IFS=$'\n'
                     COMPREPLY=($(compgen -f "${cur}"))
+                    if [[ -v oldifs ]]; then
+                        IFS="$oldifs"
+                    fi
                     if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then
                         compopt -o filenames
                     fi
                     return 0
                     ;;
                 -f)
+                    local oldifs
+                    if [[ -v IFS ]]; then
+                        oldifs="$IFS"
+                    fi
+                    IFS=$'\n'
                     COMPREPLY=($(compgen -f "${cur}"))
+                    if [[ -v oldifs ]]; then
+                        IFS="$oldifs"
+                    fi
                     if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then
                         compopt -o filenames
                     fi
diff --git a/clap_complete/tests/testsuite/bash.rs b/clap_complete/tests/testsuite/bash.rs
index 1392294bd2d..937f112cfcd 100644
--- a/clap_complete/tests/testsuite/bash.rs
+++ b/clap_complete/tests/testsuite/bash.rs
@@ -222,6 +222,27 @@ fn complete() {
         );
     }
 
+    // Issue 5313 (https://github.com/clap-rs/clap/issues/5313)
+    {
+        use std::fs::File;
+        use std::path::Path;
+
+        let testdir = snapbox::path::PathFixture::mutable_temp().unwrap();
+        let testdir_path = testdir.path().unwrap();
+
+        File::create(Path::new(testdir_path).join("foo bar.txt")).unwrap();
+        File::create(Path::new(testdir_path).join("baz\tqux.txt")).unwrap();
+
+        let input = format!(
+            "exhaustive hint --file {}/\t\t",
+            testdir_path.to_string_lossy()
+        );
+        let expected = r#"% 
+foo bar.txt   baz^Iqux.txt  "#;
+        let actual = runtime.complete(input.as_str(), &term).unwrap();
+        snapbox::assert_eq(expected, actual);
+    }
+
     let input = "exhaustive hint --other \t";
     let expected = "exhaustive hint --other         % exhaustive hint --other ";
     let actual = runtime.complete(input, &term).unwrap();