2

I want to have ls ignore (ommit from its output) any and all filenames that are listed in a .hidden file.

I found a bash function that appears to override ls to do this...

ls () {
  if [ -f .hidden ]; then
    declare GLOBIGNORE="$GLOBIGNORE:.*:$(tr '\n' ':' < .hidden)"
    ls "$@"
  fi
}

...but when I source .bashrc it returns

-bash: .bashrc: line 121: syntax error near unexpected token `('
-bash: .bashrc: line 121: `ls () {'

I can't identity the syntax error myself (I've done a little bash scripting, but the declare GLOBIGNORE line is foreign to me). Line 121 is just this: ls () { which seems fine itself.

Do you see an error in this function?

Is there another approach that could be used?


updates:

Deleting the alias ls='ls --color=auto' from .bashrc doesn't solve the unexpected token error. As per advice, let's abandon that approach using globignore.

When @rkhff pointed out the -I (and --ignore=) I had the thought to try something like this (in a function first before placing in bashrc)

PARAM=''
if [ -f .hidden ]; then
  IGN=' -I '
  while read p; do
    $PARAM+=$IGN$p
    #$PARAM="${PARAM}${IGN}${p}"
  done < .hidden
fi
ls$PARAM

but that gives this mysteriously /home/alec/bin/ls.sh: line 7: +=: command not found.... why couldn't += be found? I haven't seen any other cases in my websearches where the += operator results in "command not found". The commented line with just the = also produces a command not found error. Could someone say what could be causing this?

8
  • 1
    I suspect it's because your .bashrc already defines an alias for ls, which is being expanded when it tries to parse the function definition so that you end up with something like ls --color=auto () { Mar 23, 2020 at 15:53
  • Yes you're correct inside default Kubuntu .bashrc: if [ -x /usr/bin/dircolors ]; then includes that line you mentioned.
    – alec
    Mar 23, 2020 at 16:04
  • @steeldriver could you provide an answer that modifies the function I posted to include this --color=auto() bit? Then I'll delete that alias that came with the default file. That'd be sweet :)
    – alec
    Mar 23, 2020 at 16:06
  • oh. but commenting-out those lines and sourcing the file again still results in the same error.
    – alec
    Mar 23, 2020 at 16:09
  • 1
    I don't think you can use a file to define file names that should not be listed in the output of ls. As an alternative, you can use the -I (capital i) option, perhaps as an alias.
    – rkhff
    Mar 23, 2020 at 18:57

1 Answer 1

2

The error is likely because you have an earlier alias definition for ls. To demonstrate:

$ alias foo='echo foobar'
$ foo
foobar
$ foo () { echo barfoo; }
-bash: syntax error near unexpected token `('

However, I don't think you will be able to do what you want with GLOBIGNORE, since it only affects how the shell expands globs, and your shell will expand any glob expressions before your ls command is invoked.

At least with the GNU Coreutils implementation of ls, you may however be able to use the -I or --ignore switch ex.

hidls () 
{ 
    declare -a args;
    local pat;
    local patfile=".hidden";
    [[ -r $patfile ]] || { 
        command ls "$@";
        return
    };
    while IFS= read -r pat; do
        args+=("-I");
        args+=("$pat");
    done < "$patfile";
    command ls "${args[@]}" "$@"
}
alias ls=hidls
9
  • 1
    Aside from foo () { … Bash supports function foo { … syntax which does not collide with already defined alias. Mar 23, 2020 at 19:45
  • @KamilMaciorowski ah that's good to know - thanks Mar 23, 2020 at 20:17
  • This seems slightly more complicated than a while loop... is there a reason for using mapfile and for loop instead of a while loop? Is the || return supposed to work in place of an if statement?
    – alec
    Mar 23, 2020 at 23:57
  • If the current directory does not have a file named .hidden the bash errors No such file or directory. Should it have some logic like [ -f $1/.hidden ] ?
    – alec
    Mar 24, 2020 at 0:02
  • 1
    @alec DO NOT OMIT the command in command ls. The explanation I had given you to the the other question (which you have deleted) was correct: aliases are expanded in the body of functions when the functions are defined, not when they're run.
    – mosvy
    Mar 24, 2020 at 2:01

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.