1

Main question: how would one get the delta for declare -F, between that in the current shell, and that as if the shell just started (first two commands below). $(declare -F) does not solve the problem because the subshell is a copy of the shell process. Subsidiary: why does the third command below output nothing?

$ exec env -i bash                   
$ declare -F      
declare -f ShowInstallerIsoInfo
declare -f __expand_tilde_by_ref
declare -f __get_cword_at_cursor_by_ref
declare -f __load_completion
declare -f __ltrim_colon_completions
declare -f __parse_options
declare -f __reassemble_comp_words_by_ref
declare -f _allowed_groups
declare -f _allowed_users
declare -f _available_interfaces
declare -f _bashcomp_try_faketty
declare -f _bq_completer
declare -f _cd
declare -f _cd_devices
declare -f _command
declare -f _command_offset
declare -f _complete_as_root
declare -f _completer
declare -f _completion_loader
declare -f _configured_interfaces
declare -f _count_args
declare -f _dvd_devices
declare -f _expand
declare -f _filedir
declare -f _filedir_xspec
declare -f _fstypes
declare -f _get_comp_words_by_ref
declare -f _get_cword
declare -f _get_first_arg
declare -f _get_pword
declare -f _gids
declare -f _have
declare -f _included_ssh_config_files
declare -f _init_completion
declare -f _installed_modules
declare -f _ip_addresses
declare -f _kernel_versions
declare -f _known_hosts
declare -f _known_hosts_real
declare -f _longopt
declare -f _mac_addresses
declare -f _minimal
declare -f _modules
declare -f _ncpus
declare -f _open_files_for_editing
declare -f _parse_help
declare -f _parse_usage
declare -f _pci_ids
declare -f _pgids
declare -f _pids
declare -f _pnames
declare -f _python_argcomplete
declare -f _quote_readline_by_ref
declare -f _realcommand
declare -f _rl_enabled
declare -f _root_command
declare -f _service
declare -f _services
declare -f _shells
declare -f _signals
declare -f _split_longopt
declare -f _sysvdirs
declare -f _terms
declare -f _tilde
declare -f _uids
declare -f _upvar
declare -f _upvars
declare -f _usb_ids
declare -f _user_at_host
declare -f _usergroup
declare -f _userland
declare -f _variables
declare -f _xfunc
declare -f _xinetd_services
declare -f dequote
declare -f quote
declare -f quote_readline
$ "$SHELL" -c 'declare -F'   

Other:

$ uname -a
Linux elitebook 6.7.3-arch1-2 #1 SMP PREEMPT_DYNAMIC Fri, 02 Feb 2024 17:03:55 +0000 x86_64 GNU/Linux
$ bash --version
GNU bash, version 5.2.26(1)-release (x86_64-pc-linux-gnu)
$ echo $SHELL
/bin/bash

Update:

The clean state is an empty list of functions, as seen in the output of bash -c 'declare -F'

Based on the first command I expected the second to output two functions rather than zero.

$ grep -F -f <(declare -F | cut --delimiter=' ' --fields=3) ~/.bashrc | grep -v -E '^#' |  wc -l
2
$ bash -c 'source ~/.bashrc; declare -F'

Update2

I expected the second to output two functions rather than zero.

Here might be the reason for sourcing not taking effect:

$ cat ~/.bashrc
#
# ~/.bashrc
#

# If not running interactively, don't do anything
[[ $- != *i* ]] && return

Workaround does output two functions.

$ bash -c 'source <(grep -v '\''!= *i*'\'' ~/.bashrc); compgen -A function' 2>/dev/null
0

1 Answer 1

1

If you want to know what has changed in the list of functions since the shell started and sourced the startup files, since, in bash, function names cannot contain newline characters anyway, you can use compgen -A function to dump the list of functions one per line, and comm to compare that dump (which needs to be sorted in the same locale) at different points in time.

Add:

initial_functions=$(compgen -A function | LC_ALL=C sort)

at the end of your ~/.bashrc, then run:

LC_ALL=C comm -13 <(printf '%s\n' "$initial_functions") \
                  <(compgen -A function | LC_ALL=C sort)

To see which ones have been added since.

LC_ALL=C comm -23 <(printf '%s\n' "$initial_functions") \
                  <(compgen -A function | LC_ALL=C sort)

For the ones that have been removed.

The zsh equivalent would be:

initial_functions=( ${(k)functions} )
() { print -rC1 -- ${argv:|initial_functions}; } ${(k)functions}
() { print -rC1 -- ${initial_functions:|argv}; } ${(k)functions}

In any case, note that bash like zsh¹ doesn't define any function by itself, so the clean state is an empty list of functions, as seen in the output of bash -c 'declare -F'.

All functions that you can see have been either imported from the environment (as bash supports exporting functions via BASH_FUNC_funcname%%= environment variables with export -f) or defined in bash code that has been interpreted by bash since it started, possibly via the $BASHENV file or any of the bash startup files, some of which possibly supplied by your operating system, or files sourced from there, such as the ones from the bash-completion third party project which you seem to be using.


¹ zsh however supplies a great number of functions that you can load or autoload as example functions or to support several of its subsystems such as completion (which is not a separate project in zsh), FTP, line editor, calendar, prompt configuration, documentation, as well as a few useful tools such as zargs, zmv, zcalc...

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .