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

Issue:
Clap-generated shell completion failing on macOS /bin/bash with: conditional binary operator expected: syntax error near `IFS'
### 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

```console
❯ rustc -V
rustc 1.77.0 (aedd173a2 2024-03-17)
```

### Clap Version

4.5.3

### Minimal reproducible code

```toml
# Cargo.toml
[package]
name = "my-app"
version = "0.1.0"
edition = "2021"

[dependencies]
clap = { version = "4.5.3", features = [
  "debug",
  "derive",
  "env",
  "string",
  "wrap_help",
] }
clap_complete = "=4.5.1"
```

````rust
// src/main.rs
use clap::{CommandFactory, Parser, ValueHint};
use clap_complete::{generate, Shell};
use std::path::PathBuf;

#[derive(Parser)]
struct Opt {
    #[arg(short, long, value_hint = ValueHint::FilePath)]
    file: Option<PathBuf>,
}

fn main() {
    generate(
        Shell::Bash,
        &mut Opt::command(),
        "my-app",
        &mut std::io::stdout(),
    );
}
````


### Steps to reproduce the bug with the above code

(on a Mac)

```shell
cargo run | /bin/bash
```

### Actual Behaviour

Output:

```console
❯ cargo run | /bin/bash
    Finished dev [unoptimized + debuginfo] target(s) in 0.01s
     Running `target/debug/my-app`
/bin/bash: line 30: conditional binary operator expected
/bin/bash: line 30: syntax error near `IFS'
/bin/bash: line 30: `                    if [[ -v IFS ]]; then'
```

### Expected Behaviour

Output:

```console
❯ cargo run | /bin/bash
    Finished dev [unoptimized + debuginfo] target(s) in 0.01s
     Running `target/debug/my-app`
```

### Additional Context

On clap_complete 4.4.9 this works, on 4.4.10 this fails. I _think_ that this is a regression introduced by https://github.com/clap-rs/clap/pull/5336 . So the issue is probably the same as https://github.com/clap-rs/clap/issues/5190 , which was fixed by https://github.com/clap-rs/clap/pull/5278.

### Debug Output

```
[clap_builder::builder::command]Command::_build: name="my-app"
[clap_builder::builder::command]Command::_propagate:my-app
[clap_builder::builder::command]Command::_check_help_and_version:my-app expand_help_tree=true
[clap_builder::builder::command]Command::long_help_exists
[clap_builder::builder::command]Command::_check_help_and_version: Building default --help
[clap_builder::builder::command]Command::_propagate_global_args:my-app
[clap_builder::builder::debug_asserts]Command::_debug_asserts
[clap_builder::builder::debug_asserts]Arg::_debug_asserts:file
[clap_builder::builder::debug_asserts]Arg::_debug_asserts:help
[clap_builder::builder::debug_asserts]Command::_verify_positionals
[clap_builder::builder::command]Command::_build_bin_names
[ clap_builder::output::usage]Usage::get_required_usage_from: incls=[], matcher=false, incl_last=true
[ clap_builder::output::usage]Usage::get_required_usage_from: unrolled_reqs=[]
[ clap_builder::output::usage]Usage::get_required_usage_from: ret_val=[]
```


Discussion / hints:
This is happening too often and I'm tempted to say bash 4 is unsupported until #3166 is the default completion system since that at least reduces the risk we'll run into issues.

Fix patch:
diff --git a/clap_complete/src/shells/bash.rs b/clap_complete/src/shells/bash.rs
index 5fb39f4b965..bf361313667 100644
--- a/clap_complete/src/shells/bash.rs
+++ b/clap_complete/src/shells/bash.rs
@@ -183,12 +183,12 @@ fn option_details_for_path(cmd: &Command, path: &str) -> String {
                 if o.get_value_hint() == ValueHint::FilePath {
                     v.extend([
                         "local oldifs".to_string(),
-                        "if [[ -v IFS ]]; then".to_string(),
+                        r#"if [ -n "${IFS+x}" ]; 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#"if [ -n "${oldifs+x}" ]; then"#.to_string(),
                         r#"    IFS="$oldifs""#.to_string(),
                         "fi".to_string(),
                     ]);
@@ -216,12 +216,12 @@ fn option_details_for_path(cmd: &Command, path: &str) -> String {
                 if o.get_value_hint() == ValueHint::FilePath {
                     v.extend([
                         "local oldifs".to_string(),
-                        "if [[ -v IFS ]]; then".to_string(),
+                        r#"if [ -n "${IFS+x}" ]; 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#"if [ -n "${oldifs+x}" ]; then"#.to_string(),
                         r#"    IFS="$oldifs""#.to_string(),
                         "fi".to_string(),
                     ]);


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 a004f9148fe..bfbaec6f95f 100644
--- a/clap_complete/tests/snapshots/home/static/exhaustive/bash/.bashrc
+++ b/clap_complete/tests/snapshots/home/static/exhaustive/bash/.bashrc
@@ -557,12 +557,12 @@ _exhaustive() {
                     ;;
                 --file)
                     local oldifs
-                    if [[ -v IFS ]]; then
+                    if [ -n "${IFS+x}" ]; then
                         oldifs="$IFS"
                     fi
                     IFS=$'\n'
                     COMPREPLY=($(compgen -f "${cur}"))
-                    if [[ -v oldifs ]]; then
+                    if [ -n "${oldifs+x}" ]; then
                         IFS="$oldifs"
                     fi
                     if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then
@@ -572,12 +572,12 @@ _exhaustive() {
                     ;;
                 -f)
                     local oldifs
-                    if [[ -v IFS ]]; then
+                    if [ -n "${IFS+x}" ]; then
                         oldifs="$IFS"
                     fi
                     IFS=$'\n'
                     COMPREPLY=($(compgen -f "${cur}"))
-                    if [[ -v oldifs ]]; then
+                    if [ -n "${oldifs+x}" ]; then
                         IFS="$oldifs"
                     fi
                     if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then
diff --git a/clap_complete/tests/snapshots/value_hint.bash b/clap_complete/tests/snapshots/value_hint.bash
index e2a7f9efd37..b4cc16fab44 100644
--- a/clap_complete/tests/snapshots/value_hint.bash
+++ b/clap_complete/tests/snapshots/value_hint.bash
@@ -50,12 +50,12 @@ _my-app() {
                     ;;
                 --file)
                     local oldifs
-                    if [[ -v IFS ]]; then
+                    if [ -n "${IFS+x}" ]; then
                         oldifs="$IFS"
                     fi
                     IFS=$'\n'
                     COMPREPLY=($(compgen -f "${cur}"))
-                    if [[ -v oldifs ]]; then
+                    if [ -n "${oldifs+x}" ]; then
                         IFS="$oldifs"
                     fi
                     if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then
@@ -65,12 +65,12 @@ _my-app() {
                     ;;
                 -f)
                     local oldifs
-                    if [[ -v IFS ]]; then
+                    if [ -n "${IFS+x}" ]; then
                         oldifs="$IFS"
                     fi
                     IFS=$'\n'
                     COMPREPLY=($(compgen -f "${cur}"))
-                    if [[ -v oldifs ]]; then
+                    if [ -n "${oldifs+x}" ]; then
                         IFS="$oldifs"
                     fi
                     if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then