Launching Minishell
After building Minishell, start the shell from your build directory:
You’ll see the Minishell prompt, which displays your username and current directory:
The prompt is generated by the ft_print_user() function and updates dynamically based on your current directory.
Your First Commands
Try a Simple Built-in Command
Start with the pwd command to print your current working directory: minishell > pwd
/home/user/minishell
The implementation from builtins.c uses the getcwd() system call: void pwd ( int argc )
{
char * pwd;
if (argc > 1 )
{
printf ( "pwd: too many arguments \n " );
return ;
}
pwd = getcwd ( NULL , 0 );
printf ( " %s \n " , pwd);
free (pwd);
g_status = 0 ;
}
Display Text with Echo
Use the echo command to print text: minishell > echo Hello, Minishell!
Hello, Minishell!
Try the -n flag to suppress the newline: minishell > echo -n No newline here
No newline hereminishel l >
The echo built-in supports the -n flag just like bash, implemented in builtins.c:87-106.
Navigate Directories
Change directories using cd: minishell > cd /tmp
minishell > pwd
/tmp
minishell > cd
minishell > pwd
/home/user
Without arguments, cd takes you to your home directory: void cd ( int argc , char * av )
{
char * path;
if (argc == 1 )
path = getenv ( "HOME" );
else
path = av;
if ( chdir (path) == - 1 )
{
g_status = 1 ;
perror ( "cd" );
return ;
}
g_status = 0 ;
}
List Files with External Commands
Minishell executes external programs by searching the PATH: minishell > ls -la
total 248
drwxr-xr-x 4 user user 4096 Mar 7 12:00 .
drwxr-xr-x 28 user user 4096 Mar 6 10:30 ..
-rw-r--r-- 1 user user 2140 Mar 7 11:00 main.c
-rwxr-xr-x 1 user user 45832 Mar 7 12:00 minishell
Try other common commands: minishell > cat minishell.h
minishell > grep "typedef" minishell.h
minishell > wc -l * .c
Working with Environment Variables
Viewing Environment Variables
View All Variables
Export a New Variable
Use Variable Expansion
minishell > env
PATH = /usr/local/bin:/usr/bin:/bin
HOME = /home/user
USER = user
SHELL = /bin/bash
...
Variable Expansion
Minishell supports environment variable expansion using the $ prefix:
minishell > export GREETING=Hello
minishell > echo $GREETING World
Hello World
The expansion is handled by the vars() function in env_parsed.c:
char * vars ( char * commands , t_prompt * env , int i , int x )
{
// Parses and expands $VAR in command strings
// Handles special cases like $? for exit status
}
Special Variables
Check the exit status of the last command:
minishell > ls /nonexistent
ls: cannot access '/nonexistent': No such file or directory
minishell > echo $?
2
minishell > echo success
success
minishell > echo $?
0
Remove Variables
Use unset to remove environment variables:
minishell > export TEMP_VAR=test
minishell > echo $TEMP_VAR
test
minishell > unset TEMP_VAR
minishell > echo $TEMP_VAR
Your First Pipeline
Pipelines connect the output of one command to the input of another using the | operator.
Basic Pipe Example
minishell > ls -l | grep minishell
-rwxr-xr-x 1 user user 45832 Mar 7 12:00 minishell
-rw-r--r-- 1 user user 4567 Mar 7 11:00 minishell.h
This pipes the output of ls -l into grep, which filters for lines containing “minishell”.
Multi-Command Pipeline
Chain multiple commands together:
minishell > cat * .c | grep "include" | wc -l
42
This pipeline:
Concatenates all .c files (cat *.c)
Filters for lines with “include” (grep "include")
Counts the matching lines (wc -l)
How Pipes Work
Minishell creates separate processes for each command and connects them:
// From ft_execute_commands.c - Pipeline execution
void excecute_pipe_sequence (t_mini * data , int pipefd [ 2 ])
{
int aux [ 2 ];
aux [ 0 ] = - 1 ;
aux [ 1 ] = - 1 ;
while ( data -> nodes [ ++ aux [ 0 ]])
{
if ( pipe (pipefd) == - 1 )
return ;
data -> nodes [ aux [ 0 ]]-> n_pid = fork ();
if ( data -> nodes [ aux [ 0 ]]-> n_pid == 0
&& data -> nodes [ aux [ 0 ]]-> is_set == 1 )
child_process (data, data -> nodes [ aux [ 0 ]], aux, pipefd);
// Parent process continues...
}
}
Output Redirection
Redirect command output to a file:
Overwrite File
Append to File
minishell > echo "Hello" > output.txt
minishell > cat output.txt
Hello
minishell > ls -l > filelist.txt
Read command input from a file:
minishell > echo "apple\nbanana\ncherry" > fruits.txt
minishell > wc -l < fruits.txt
3
Heredoc (<<)
Provide multi-line input interactively:
minishell > cat << EOF
> This is line 1
> This is line 2
> This is line 3
> EOF
This is line 1
This is line 2
This is line 3
The heredoc is handled by the check_heredoc() function:
void check_heredoc ( char * limit , int * infile )
{
int fd;
char * line;
fd = open (TEMP_FILE, O_CREAT | O_WRONLY | O_TRUNC, 0 644 );
while ( 1 )
{
line = readline ( ">" );
if ( ! line || ( ! ft_strncmp (line, limit, ft_strlen (limit))))
break ;
write (fd, line, strlen (line));
write (fd, " \n " , 1 );
}
close (fd);
* infile = open (TEMP_FILE, O_RDONLY);
}
Combining Redirections
You can combine multiple redirections:
minishell > cat < input.txt > output.txt
minishell > grep "error" < logfile.txt >> errors.txt
minishell > cat << END | grep "test" > results.txt
> test line 1
> other line
> test line 2
> END
Quote Handling
Minishell properly handles single and double quotes:
Single Quotes
Double Quotes
Mixed Quotes
minishell > echo 'Hello $USER'
Hello $USER
# Variables NOT expanded in single quotes
Quotes are removed before command execution by the remove_quotes() function in parse_imput.c.
Signal Handling
Minishell responds to keyboard signals:
Ctrl+C (SIGINT): Cancels current command and displays a new prompt
Ctrl+D (EOF): Exits the shell when pressed on an empty line
*Ctrl+* (SIGQUIT): Ignored in interactive mode (unlike bash)
// From signals.c - Signal setup
void setup_signals ( void )
{
signal (SIGINT, handle_sigint);
signal (SIGQUIT, SIG_IGN);
}
void handle_sigint ( int sig )
{
g_status = 130 ;
write ( 1 , " \n " , 1 );
rl_on_new_line ();
rl_replace_line ( "" , 0 );
rl_redisplay ();
}
Exiting the Shell
There are three ways to exit Minishell:
minishell > exit
# Exits with status 0
minishell > exit 42
# Exits with status 42
Practical Examples
Example 1: File Processing Pipeline
minishell > cat employees.txt | grep "Engineer" | wc -l
15
Counts how many employees are engineers.
Example 2: Log Analysis
minishell > grep "ERROR" app.log > errors.txt
minishell > wc -l < errors.txt
27
minishell > cat errors.txt | head -5
Extracts errors from a log file and examines them.
Example 3: Environment Setup
minishell > export PROJECT_DIR=/home/user/project
minishell > export PATH= $PATH : $PROJECT_DIR /bin
minishell > cd $PROJECT_DIR
minishell > pwd
/home/user/project
Configures project-specific environment variables.
minishell > cat data.csv | cut -d ',' -f2 | sort | uniq > unique_values.txt
Extracts the second column from a CSV, sorts it, and removes duplicates.
Command History
Minishell uses GNU Readline for command history:
Up Arrow : Navigate to previous commands
Down Arrow : Navigate to next commands
Ctrl+R : Search command history (if enabled)
History is managed automatically:
// From main.c - Adding to history
void enterdata ( char * line , t_mini * data , int i )
{
add_history (line);
// Process command...
}
Common Pitfalls
Unclosed Quotes : Minishell detects unclosed quotes and reports syntax errors:minishell > echo "hello
syntax error: unclosed quotes
Invalid Pipes : Empty pipe segments cause errors:minishell > ls | | grep test
syntax error near unexpected token '|'
Redirection Errors : Missing filenames after redirection operators:minishell > echo "test" >
syntax error near unexpected token 'newline'
Next Steps
Now that you understand the basics, explore more advanced features:
Built-in Commands Detailed reference for all built-in commands
Pipelines Advanced pipeline techniques
Redirections Input and output redirection
Environment Variables Managing and using environment variables