wordexp(3)

โœจ wordexp(3) โœจ

like, shell expansion but make it a C function ๐Ÿ’…

okay bestie so you know how your shell does all that cute ~ and $FOO and *.c magic before it runs anything? wordexp is literally that, but callable from C. it's from the Library Functions Manual and it lives in the Standard C library (libc, -lc). it's giving "we have a shell at home" and the shell at home is THIS. ๐Ÿ”ฅ


๐ŸŒธ NAME ๐ŸŒธ

wordexp, wordfree โ€” perform word expansion like a posix-shell


๐ŸŽ€ LIBRARY ๐ŸŽ€

Standard C library (libc, -lc)


๐Ÿฆ‹ SYNOPSIS ๐Ÿฆ‹

#include <wordexp.h>

int wordexp(const char *restrict s, wordexp_t *restrict p, int flags);
void wordfree(wordexp_t *p);

Feature Test Macro Requirements for glibc (see feature_test_macros(7)):

wordexp(), wordfree():
    _XOPEN_SOURCE

๐Ÿ’– DESCRIPTION ๐Ÿ’–

so the function wordexp() performs a shell-like expansion of the string s and hands you back the result in the structure pointed to by p. ๐Ÿซถ

the data type wordexp_t is a structure that at least has the fields we_wordc, we_wordv, and we_offs. let's break it down:

  • we_wordc โ€” a size_t giving the number of words in the expansion of s. it's the headcount, the guest list. ๐Ÿ‘‘
  • we_wordv โ€” a char ** pointing to the array of words found. this is the main character, the actual content.
  • we_offs โ€” type size_t, and it is sometimes used (depending on flags, see below) to indicate how many initial elements in the we_wordv array should be filled with NULLs. it's the "leave some seats empty at the front" field. ๐Ÿ’€

then the function wordfree() frees the allocated memory again. and ngl, be precise about this: it does not free its argument โ€” it frees the array we_wordv and the strings that it points to. the struct itself is your problem, bestie.

๐Ÿ“ The string argument ๐Ÿ“

since the expansion is the same as the expansion by the shell (see sh(1)) of the parameters to a command, the string s must not contain characters that would be illegal in shell command parameters. specifically, there must not be any unescaped newline or |, &, ;, <, >, (, ), {, } characters outside a command substitution or parameter substitution context. so like, don't be weird with it. ๐Ÿ™ˆ

if the argument s contains a word that starts with an unquoted comment character #, then it is unspecified whether that word and all following words are ignored, or the # is treated as a non-comment character. yes, unspecified, no cap. don't build your life on it.

๐ŸŒˆ The expansion ๐ŸŒˆ

the expansion done consists of the following stages, in order, and this is the whole lineup:

  • tilde expansion โ€” replacing ~user by user's home directory
  • variable substitution โ€” replacing $FOO by the value of the environment variable FOO
  • command substitution โ€” replacing $(command) or `command` by the output of command
  • arithmetic expansion
  • field splitting
  • wildcard expansion
  • quote removal

the result of expansion of special parameters ($@, $*, $#, $?, $-, $$, $!, $0) is unspecified. ๐Ÿ˜ญ

field splitting is done using the environment variable $IFS. if it is not set, the field separators are space, tab, and newline. iconic default behavior honestly.

โญ The output array โญ

the array we_wordv contains the words found, followed by a NULL. terminating NULL, as a treat. ๐ŸŽ€

๐Ÿ’… The flags argument ๐Ÿ’…

the flag argument is a bitwise inclusive OR of the following values:

  • WRDE_APPEND โ€” append the words found to the array resulting from a previous call. (stacking, we love a sequel)
  • WRDE_DOOFFS โ€” insert we_offs initial NULLs in the array we_wordv. (these are not counted in the returned we_wordc. read that again, bestie, it matters)
  • WRDE_NOCMD โ€” don't do command substitution.
  • WRDE_REUSE โ€” the argument p resulted from a previous call to wordexp(), and wordfree() was not called. reuse the allocated storage.
  • WRDE_SHOWERR โ€” normally during command substitution stderr is redirected to /dev/null. this flag specifies that stderr is not to be redirected. (show me the errors, i want the drama ๐Ÿ”ฅ)
  • WRDE_UNDEF โ€” consider it an error if an undefined shell variable is expanded.

๐Ÿ”ฅ RETURN VALUE ๐Ÿ”ฅ

on success, wordexp() returns 0. periodt. โœจ

on failure, wordexp() returns one of the following nonzero values:

  • WRDE_BADCHAR โ€” illegal occurrence of newline or one of |, &, ;, <, >, (, ), {, }.
  • WRDE_BADVAL โ€” an undefined shell variable was referenced, and the WRDE_UNDEF flag told us to consider this an error.
  • WRDE_CMDSUB โ€” command substitution requested, but the WRDE_NOCMD flag told us to consider this an error.
  • WRDE_NOSPACE โ€” out of memory.
  • WRDE_SYNTAX โ€” shell syntax error, such as unbalanced parentheses or unmatched quotes.

๐Ÿงš ATTRIBUTES ๐Ÿงš

for an explanation of the terms used in this section, see attributes(7).

  • wordexp() โ€” Thread safety: MT-Unsafe race:utent const:env env sig:ALRM timer locale
  • wordfree() โ€” Thread safety: MT-Safe

in the above list, utent in race:utent signifies that if any of the functions setutent(3), getutent(3), or endutent(3) are used in parallel in different threads of a program, then data races could occur. wordexp() calls those functions, so we use race:utent to remind users. consider this your friendly little heads-up note taped to the mirror. ๐Ÿ’œ


๐Ÿ’œ STANDARDS ๐Ÿ’œ

POSIX.1-2008.


๐ŸŒธ HISTORY ๐ŸŒธ

POSIX.1-2001. glibc 2.1.


๐Ÿ‘‘ EXAMPLES ๐Ÿ‘‘

the output of the following example program is approximately that of "ls [a-c]*.c".

#include <stdio.h>
#include <stdlib.h>
#include <wordexp.h>

int
main(void)
{
    wordexp_t p;
    char **w;

    wordexp("[a-c]*.c", &p, 0);
    w = p.we_wordv;
    for (size_t i = 0; i < p.we_wordc; i++)
        printf("%s\n", w[i]);
    wordfree(&p);
    exit(EXIT_SUCCESS);
}

๐Ÿฆ‹ SEE ALSO ๐Ÿฆ‹

fnmatch(3), glob(3)


okay that's the whole thing, you ate it, you understood it, you're literally a shell expansion girly now ๐Ÿซถ๐Ÿ’–

this little love letter is from the Linux man-pages, version 6.20, dated 2026-02-08, for wordexp(3). mwah, go read glob(3) next, i'll wait. ๐ŸŽ€โœจ

๐Ÿ“ฆ where this page comes from
  • arch rolling: man-pages 6.20-1 ยท BSD-2-Clause AND BSD-3-Clause AND BSD-4.3TAHOE AND BSD-4-Clause-UC AND GPL-1.0-or-later AND GPL-2.0-only AND GPL-2.0-or-later AND GPL-3.0-or-later AND LGPL-3.0-linking-exception AND LGPL-3.0-or-later AND LicenseRef-Public-Domain AND LicenseRef-UltraPermissive AND Linux-man-pages-1-para AND Linux-man-pages-copyleft AND Linux-man-pages-copyleft-2-para AND Linux-man-pages-copyleft-var AND MIT AND Spencer-94
  • nixpkgs unstable: man-pages 6.20
  • ๐Ÿ“œ the page's license: GPL-2.0-or-later
  • ๐Ÿ’– girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms