On 3/15/11 4:44 PM, Chet Ramey wrote: >> Bash Version: 4.2 >> Patch Level: 7 >> Release Status: release >> >> Description: >> When enter in console "ls $HOME/" and press TAB for >> completion, then bash add slash for special characters like $ { } >> When I back to wersion 4.1_p10 then problem is gone. Problem >> also exists with 4.2_p6 and 4.2_p1 (these veriosn I have checked). > > The difference is that bash-4.1 expanded $HOME and left the expansion > as part of the replacement text. Bash-4.2 tries to leave what the > user typed alone, but that leads to an inherently ambiguous situation: > when do you quote the `$' in a filename (or, in this case, a directory > name)? It could be a shell variable, and it could be a character in > the filename.
I've attached a patch that applies a heuristic. If the directory name contains a variable, and bash expands it, it removes the appropriate characters from the set that causes readline to ask bash to quote the filename. It's the 90% solution. It is not perfect: if a character in the filename needs to be quoted, bash will still quote the `$' in the directory name. It should handle most of the cases, however. If you're interested, apply it with `patch -p0' and see whether or not it works. Chet -- ``The lyf so short, the craft so long to lerne.'' - Chaucer ``Ars longa, vita brevis'' - Hippocrates Chet Ramey, ITS, CWRU c...@case.edu http://cnswww.cns.cwru.edu/~chet/
*** ../bash-4.2-patched/bashline.c 2011-01-16 15:32:47.000000000 -0500 --- bashline.c 2011-03-16 17:10:20.000000000 -0400 *************** *** 248,251 **** --- 250,256 ---- /* )) */ + static const char *default_filename_quote_characters = " \t\n\\\"'@<>=;|&()#$`?*[!:{~"; /*}*/ + static char *custom_filename_quote_characters = 0; + static rl_hook_func_t *old_rl_startup_hook = (rl_hook_func_t *)NULL; *************** *** 530,534 **** /* characters that need to be quoted when appearing in filenames. */ ! rl_filename_quote_characters = " \t\n\\\"'@<>=;|&()#$`?*[!:{~"; /*}*/ rl_filename_quoting_function = bash_quote_filename; --- 535,539 ---- /* characters that need to be quoted when appearing in filenames. */ ! rl_filename_quote_characters = default_filename_quote_characters; rl_filename_quoting_function = bash_quote_filename; *************** *** 567,570 **** --- 574,578 ---- rl_directory_rewrite_hook = bash_directory_completion_hook; rl_ignore_some_completions_function = filename_completion_ignore; + rl_filename_quote_characters = default_filename_quote_characters; } *************** *** 1280,1283 **** --- 1288,1293 ---- rl_ignore_some_completions_function = filename_completion_ignore; + rl_filename_quote_characters = default_filename_quote_characters; + /* Determine if this could be a command word. It is if it appears at the start of the line (ignoring preceding whitespace), or if it *************** *** 2703,2720 **** { char *local_dirname, *new_dirname, *t; ! int return_value, should_expand_dirname; WORD_LIST *wl; struct stat sb; ! return_value = should_expand_dirname = 0; local_dirname = *dirname; ! if (mbschr (local_dirname, '$')) ! should_expand_dirname = 1; else { t = mbschr (local_dirname, '`'); if (t && unclosed_pair (local_dirname, strlen (local_dirname), "`") == 0) ! should_expand_dirname = 1; } --- 2713,2741 ---- { char *local_dirname, *new_dirname, *t; ! int return_value, should_expand_dirname, nextch, closer; WORD_LIST *wl; struct stat sb; ! return_value = should_expand_dirname = nextch = closer = 0; local_dirname = *dirname; ! if (t = mbschr (local_dirname, '$')) ! { ! should_expand_dirname = '$'; ! nextch = t[1]; ! /* Deliberately does not handle the deprecated $[...] arithmetic ! expansion syntax */ ! if (nextch == '(') ! closer = ')'; ! else if (nextch == '{') ! closer = '}'; ! else ! nextch = 0; ! } else { t = mbschr (local_dirname, '`'); if (t && unclosed_pair (local_dirname, strlen (local_dirname), "`") == 0) ! should_expand_dirname = '`'; } *************** *** 2740,2743 **** --- 2761,2781 ---- dispose_words (wl); local_dirname = *dirname; + /* XXX - change rl_filename_quote_characters here based on + should_expand_dirname/nextch/closer. This is the only place + custom_filename_quote_characters is modified. */ + if (rl_filename_quote_characters && *rl_filename_quote_characters) + { + int i, j, c; + i = strlen (default_filename_quote_characters); + custom_filename_quote_characters = xrealloc (custom_filename_quote_characters, i+1); + for (i = j = 0; c = default_filename_quote_characters[i]; i++) + { + if (c == should_expand_dirname || c == nextch || c == closer) + continue; + custom_filename_quote_characters[j++] = c; + } + custom_filename_quote_characters[j] = '\0'; + rl_filename_quote_characters = custom_filename_quote_characters; + } } else