\chapter{Linux Commands} \ChapterLabel{LinuxCommands} \index{Linux} \index{Linux!command line} \index{Linux!working directory} \index{bash} \index{symbolic link} \index{file timestamps} \section{Purpose} This chapter records a set of Linux shell commands run in the authors' working user directories, and the solutions to the accompanying problem set. Terminal input and output are copied directly from the shell, so each listing is a record of an actual execution and serves as \gls{evidence} for this chapter. \section{Environment} \index{Linux!environment} The commands were run as the unprivileged user \texttt{payton} on Ubuntu~24.04 under the \gls{wsl} on the author's workstation, in a \texttt{bash} shell. \section{Working Directory Setup} \index{Linux!working directory setup} Figure~\ref{Figure:LxTestSetup} shows the executed setup commands in the order given by the assignment. Figure~{\ref{Figure:LxTestDirectories}} shows the resulting directory structure, and Figure~{\ref{Figure:LxTestFiles}} shows the resulting file contents. \subsection{What the Commands Do} \index{Linux!command explanations} \begin{sloppypar} \begin{itemize}[leftmargin=*] \item \texttt{mkdir -p \textasciitilde/lx-test \&\& cd \textasciitilde/lx-test} creates the directory, along with any missing parent directories, and does not fail if it already exists. The \texttt{\&\&} operator runs \texttt{cd} only if \texttt{mkdir} succeeds. \item \texttt{printf "\ldots" > \textit{file}} writes the string to a file, turning each \texttt{\textbackslash n} into a newline. The \texttt{>} redirection creates the file or overwrites it if it already exists. \texttt{printf} is used instead of \texttt{echo} because it handles escape sequences the same way in every shell. \item \texttt{dd} with \texttt{if=/dev/zero}, \texttt{of=blob.bin}, \texttt{bs=1K}, and \texttt{count=48} copies $48$ blocks of $1\,\mathrm{KiB}$ from \texttt{/dev/zero}, producing a file of $48 \times 1024 = 49152$ zero bytes. \item \texttt{mkdir -p src/lib tmp archive} creates three directories in one command; \texttt{-p} creates \texttt{src} as the parent of \texttt{lib}. \item \texttt{ln -s src/file1.txt link-to-file1} creates a symbolic link. The stored target is the relative path \texttt{src/file1.txt}, which is resolved relative to the directory that contains the link. \item \texttt{touch -t 202401020304 old.txt} creates \texttt{old.txt} with a modification time of 2024-01-02 03:04 in local time. \item \texttt{ls -lA} lists each named directory in long format, including hidden entries but omitting \texttt{.} and \texttt{..}. \texttt{head} prints the first ten lines of each file under a file name header; every file here is shorter than ten lines, so each is shown in full. \end{itemize} \end{sloppypar} \subsection{Interpretation of Results} \index{Linux!result interpretation} Figure~\ref{Figure:LxTestDirectories} confirms each step of the setup: \begin{itemize}[leftmargin=*] \item \textbf{File sizes:} \texttt{blob.bin} is $49152$ bytes, as computed above. Each text file's size equals its characters plus one byte per newline. \item \textbf{Symbolic link:} \texttt{link-to-file1} has type \texttt{l} and points to \texttt{src/file1.txt}. \item \textbf{Timestamp:} \texttt{old.txt} is empty and shows the modified timestamp (\texttt{Jan~2~2024}). \item \textbf{Directories:} \texttt{archive}, \texttt{tmp}, and \texttt{src/lib} report \texttt{total 0}, confirming they exist and are empty. \item \textbf{Permissions:} New files are \texttt{rw-r--r--} ($644$) and new directories are \texttt{rwxr-xr-x} ($755$). \end{itemize} \begin{figure}[htbp] \begin{lstlisting}[numbers=none, columns=fullflexible, keepspaces=true] payton@paytonpc:~$ mkdir -p ~/lx-test && cd ~/lx-test payton@paytonpc:~/lx-test$ printf "alpha\nbeta\nGamma\ngamma\nbeta\n" > words.txt payton@paytonpc:~/lx-test$ printf "id,name,dept\n1,Ada,EE\n2,Linus,CS\n3,Grace,EE\n4,Dennis,CS\n" > people.csv payton@paytonpc:~/lx-test$ printf "INFO boot ok\nWARN disk low\nERROR fan fail\nINFO shutdown\n" > sys.log payton@paytonpc:~/lx-test$ dd if=/dev/zero of=blob.bin bs=1K count=48 status=none payton@paytonpc:~/lx-test$ mkdir -p src/lib tmp archive payton@paytonpc:~/lx-test$ printf "one two three four\n" > src/file1.txt payton@paytonpc:~/lx-test$ printf "two three four five\n" > src/file2.txt payton@paytonpc:~/lx-test$ ln -s src/file1.txt link-to-file1 payton@paytonpc:~/lx-test$ touch -t 202401020304 old.txt \end{lstlisting} \caption{Terminal input for setting up the \texttt{lx-test} working directory.} \label{Figure:LxTestSetup} \end{figure} \begin{figure}[htbp] \begin{lstlisting}[numbers=none, columns=fullflexible, keepspaces=true] payton@paytonpc:~/lx-test$ ls -lA . src src/lib archive tmp .: total 72 drwxr-xr-x 2 payton payton 4096 Sep 26 15:39 archive -rw-r--r-- 1 payton payton 49152 Sep 26 15:39 blob.bin lrwxrwxrwx 1 payton payton 13 Sep 26 15:39 link-to-file1 -> src/file1.txt -rw-r--r-- 1 payton payton 0 Jan 2 2024 old.txt -rw-r--r-- 1 payton payton 56 Sep 26 15:39 people.csv drwxr-xr-x 3 payton payton 4096 Sep 26 15:39 src -rw-r--r-- 1 payton payton 56 Sep 26 15:39 sys.log drwxr-xr-x 2 payton payton 4096 Sep 26 15:39 tmp -rw-r--r-- 1 payton payton 28 Sep 26 15:39 words.txt archive: total 0 src: total 12 -rw-r--r-- 1 payton payton 19 Sep 26 15:39 file1.txt -rw-r--r-- 1 payton payton 20 Sep 26 15:39 file2.txt drwxr-xr-x 2 payton payton 4096 Sep 26 15:39 lib src/lib: total 0 tmp: total 0 \end{lstlisting} \caption{Terminal output showing the resulting directories after \texttt{lx-test} setup.} \label{Figure:LxTestDirectories} \end{figure} \begin{figure}[htbp] \begin{lstlisting}[numbers=none, columns=fullflexible, keepspaces=true] payton@paytonpc:~/lx-test$ head words.txt people.csv sys.log src/file1.txt src/file2.txt ==> words.txt <== alpha beta Gamma gamma beta ==> people.csv <== id,name,dept 1,Ada,EE 2,Linus,CS 3,Grace,EE 4,Dennis,CS ==> sys.log <== INFO boot ok WARN disk low ERROR fan fail INFO shutdown ==> src/file1.txt <== one two three four ==> src/file2.txt <== two three four five \end{lstlisting} \caption{Terminal output showing the resulting file contents after \texttt{lx-test} setup.} \label{Figure:LxTestFiles} \end{figure} \section{Problem Set Solutions} \index{Linux!problem set} \subsection{Navigation and File Operations} \begin{enumerate}[label=\arabic*., leftmargin=*] \item Show your present working directory path only. \begin{lstlisting}[style=cmd] $ pwd \end{lstlisting} \item List all entries in the current directory, one per line, including dotfiles. \begin{lstlisting}[style=cmd] $ ls -1a \end{lstlisting} \item Copy \texttt{src/file1.txt} to \texttt{tmp/} only if \texttt{tmp} exists; do it verbosely. \begin{lstlisting}[style=cmd] $ [ -d tmp ] && cp -v src/file1.txt tmp/ \end{lstlisting} \item Move \texttt{old.txt} into \texttt{archive/} and keep its original timestamp. \begin{lstlisting}[style=cmd] $ mv old.txt archive/ \end{lstlisting} \item Create a new empty file \texttt{notes.md} only if it doesn't already exist. \begin{lstlisting}[style=cmd] $ [ -e notes.md ] || touch notes.md \end{lstlisting} \item Show disk usage (human-readable) for the \texttt{src} directory only (not total FS). \begin{lstlisting}[style=cmd] $ du -sh src \end{lstlisting} \end{enumerate} \subsection{Viewing and Searching} \begin{enumerate}[label=\arabic*., leftmargin=*, resume] \item Print line numbers while displaying \texttt{sys.log}. \begin{lstlisting}[style=cmd] $ cat -n sys.log \end{lstlisting} \item Show only the lines in \texttt{sys.log} that contain \texttt{ERROR} (case-sensitive). \begin{lstlisting}[style=cmd] $ grep 'ERROR' sys.log \end{lstlisting} \item Count how many distinct words appear in \texttt{words.txt} (case-insensitive). \begin{lstlisting}[style=cmd] $ tr '[:upper:]' '[:lower:]' < words.txt | sort -u | wc -l \end{lstlisting} \item From \texttt{words.txt}, show lines that start with \texttt{g} or \texttt{G}. \begin{lstlisting}[style=cmd] $ grep '^[gG]' words.txt \end{lstlisting} \item Display the first 2 lines of \texttt{people.csv} without using an editor. \begin{lstlisting}[style=cmd] $ head -n 2 people.csv \end{lstlisting} \item Show the last 3 lines of \texttt{sys.log} and keep following if the file grows. \begin{lstlisting}[style=cmd] $ tail -n 3 -f sys.log \end{lstlisting} \end{enumerate} \subsection{Text Processing} \begin{enumerate}[label=\arabic*., leftmargin=*, resume] \item From \texttt{people.csv}, print only the name column (2nd), excluding the header. \begin{lstlisting}[style=cmd] $ tail -n +2 people.csv | cut -d, -f2 \end{lstlisting} \item Sort \texttt{words.txt} case-insensitively and remove duplicates. \begin{lstlisting}[style=cmd] $ sort -fu words.txt \end{lstlisting} \item Replace every \texttt{three} with \texttt{3} in all files under \texttt{src/} in-place, creating \texttt{.bak} backups. \begin{lstlisting}[style=cmd] $ find src -type f -name '*.txt' -exec sed -i.bak 's/three/3/g' {} + \end{lstlisting} \item Print the number of lines, words, and bytes for every \texttt{*.txt} file in \texttt{src/}. \begin{lstlisting}[style=cmd] $ wc src/*.txt \end{lstlisting} \end{enumerate} \subsection{Permissions and Ownership} \begin{enumerate}[label=\arabic*., leftmargin=*, resume] \item Make \texttt{tmp/} readable, writable, and searchable only by the owner. \begin{lstlisting}[style=cmd] $ chmod 700 tmp/ \end{lstlisting} \item Give group execute permission to \texttt{src/lib} recursively without touching others/owner bits. \begin{lstlisting}[style=cmd] $ chmod -R g+x src/lib \end{lstlisting} \item Show the numeric (octal) permissions of \texttt{src/file2.txt}. \begin{lstlisting}[style=cmd] $ stat -c '%a' src/file2.txt \end{lstlisting} \item Make \texttt{notes.md} append-only for the owner via file attributes (if supported). \begin{lstlisting}[style=cmd] $ sudo chattr +a notes.md \end{lstlisting} \end{enumerate} \subsection{Links and Find} \begin{enumerate}[label=\arabic*., leftmargin=*, resume] \item Verify whether \texttt{link-to-file1} is a symlink and show its target path. \begin{lstlisting}[style=cmd] $ [ -L link-to-file1 ] && readlink link-to-file1 \end{lstlisting} \item Find all regular files under the current tree larger than 40~KiB. \begin{lstlisting}[style=cmd] $ find . -type f -size +40k \end{lstlisting} \item Find files modified in the last 10 minutes under \texttt{tmp/} and print their sizes. \begin{lstlisting}[style=cmd] $ find tmp/ -type f -mmin -10 -printf '%p %s\n' \end{lstlisting} \end{enumerate} \subsection{Processes and Job Control} \begin{enumerate}[label=\arabic*., leftmargin=*, resume] \item Show your processes in a tree view. \begin{lstlisting}[style=cmd] $ pstree -p "$USER" \end{lstlisting} \item Start \texttt{sleep 120} in the background and show its PID. \begin{lstlisting}[style=cmd] $ sleep 120 & echo $! \end{lstlisting} \item Send a TERM signal to all \texttt{sleep} processes owned by you (don't use \texttt{kill -9}). \begin{lstlisting}[style=cmd] $ pkill -TERM -u "$USER" -x sleep \end{lstlisting} \item Show the top 5 processes by memory usage (one-shot, not interactive). \begin{lstlisting}[style=cmd] $ ps aux --sort=-%mem | head -n 6 \end{lstlisting} \end{enumerate} \subsection{Archiving and Compression} \begin{enumerate}[label=\arabic*., leftmargin=*, resume] \item Create a gzipped tar archive \texttt{src.tgz} from \texttt{src/} with relative paths. \begin{lstlisting}[style=cmd] $ tar -czf src.tgz src/ \end{lstlisting} \item List the contents of \texttt{src.tgz} without extracting. \begin{lstlisting}[style=cmd] $ tar -tzf src.tgz \end{lstlisting} \item Extract only \texttt{file2.txt} from \texttt{src.tgz} into \texttt{tmp/}. \begin{lstlisting}[style=cmd] $ tar -xzvf src.tgz -C tmp/ --strip-components=1 src/file2.txt \end{lstlisting} \end{enumerate} \subsection{Networking and System Information} \begin{enumerate}[label=\arabic*., leftmargin=*, resume] \item Show all listening TCP sockets with associated PIDs (no root assumptions). \begin{lstlisting}[style=cmd] $ ss -ltnp \end{lstlisting} \item Print your default route (gateway) in a concise form. \begin{lstlisting}[style=cmd] $ ip route show default \end{lstlisting} \item Display kernel name, release, and machine architecture. \begin{lstlisting}[style=cmd] $ uname -srm \end{lstlisting} \item Show the last 5 successful logins (or last sessions) on the system. \begin{lstlisting}[style=cmd] $ last -n 5 \end{lstlisting} \end{enumerate} \subsection{Packages and Services (Debian/Ubuntu)} \begin{enumerate}[label=\arabic*., leftmargin=*, resume] \item Show the installed version of package \texttt{coreutils}. \begin{lstlisting}[style=cmd] $ dpkg-query -W -f='${Version}\n' coreutils \end{lstlisting} \item Search available packages whose names contain \texttt{ripgrep}. \begin{lstlisting}[style=cmd] $ apt-cache search --names-only ripgrep \end{lstlisting} \item Check whether service \texttt{cron} is active and print its status line only. \begin{lstlisting}[style=cmd] $ systemctl status cron | grep 'Active:' \end{lstlisting} \end{enumerate} \subsection{Bash and Scripting} \begin{enumerate}[label=\arabic*., leftmargin=*, resume] \item Write a one-liner that loops over \texttt{*.txt} in \texttt{src/} and prints each file's name and line count. \begin{lstlisting}[style=cmd] $ for f in src/*.txt; do echo "$f: $(wc -l < "$f")"; done \end{lstlisting} \item Write a command that exports CSV rows where \texttt{dept == "CS"} to \texttt{cs.txt} (exclude header). \begin{lstlisting}[style=cmd] $ awk -F, 'NR>1 && $3=="CS"' people.csv > cs.txt \end{lstlisting} \item Create a variable \texttt{X} with value 42, print it, then remove it from the environment. \begin{lstlisting}[style=cmd] $ export X=42; echo "$X"; unset X \end{lstlisting} \end{enumerate}