Skip to content

Commit b881060

Browse files
committed
Review the "Answers" section
1 parent 4d5ca92 commit b881060

File tree

1 file changed

+45
-43
lines changed

1 file changed

+45
-43
lines changed

manuscript/answers.md

Lines changed: 45 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ find /usr -name "*.txt"
6060

6161
The `/usr` path stores text files. So, there is no reason to check other system paths.
6262

63-
Now let's count the number of lines in the found files. We should add the `-exec` action with the `wc` utility call to do this. The resulting command looks like this:
63+
Now let's count the number of lines in the found files. The `wc` utility can do this task. We should call the utility using the `-exec` action. Then the resulting command looks like this:
6464
{line-numbers: false, format: Bash}
6565
```
6666
find /usr -name "*.txt" -exec wc -l {} +
@@ -78,95 +78,95 @@ If you add the `wc` call to the command, it fails when running in the MSYS2 envi
7878
find / -name "*.txt" -exec wc -l {} +
7979
```
8080

81-
The problem happens because of the error message that Figure 2-17 shows. The `find` utility passes the message to the `wc` input. The `wc` utility treats each word it receives as a file path. The error message is not a path. Therefore, `wc` fails.
81+
The problem happens because of the error message that Figure 2-17 shows. The `find` utility passes its error message to the `wc` input. The `wc` utility treats each word it receives as a file path. The error message is not a path. Therefore, `wc` fails.
8282

8383
##### Exercise 2-4. Searching for files with the `grep` utility
8484

8585
Look for information about application licenses in the `/usr/share/doc` system path. It contains documentation for all installed software.
8686

87-
If the program has the [GNU General Public License](https://en.wikipedia.org/wiki/GNU_General_Public_License), its documentation contains the "General Public License" line. The following command searches such documents:
87+
If the program has the [GNU General Public License](https://en.wikipedia.org/wiki/GNU_General_Public_License), its documentation contains the "General Public License" phrase. The following command searches this phrase in all documents:
8888
{line-numbers: false, format: Bash}
8989
```
9090
grep -Rl "General Public License" /usr/share/doc
9191
```
9292

93-
You also should check the files in the `/usr/share/licenses` path. Here is the command for doing that:
93+
The `/usr/share/licenses` path is the place where you can find license information for all installed software. You can search the "General Public License" phrase there with the following command:
9494
{line-numbers: false, format: Bash}
9595
```
9696
grep -Rl "General Public License" /usr/share/licenses
9797
```
9898

99-
The MSYS2 environment has two extra paths for installing programs: `/mingw32` and `/mingw64`. They do not match the POSIX standard. The following commands check documents in these paths:
99+
The MSYS2 environment has two extra paths for installing programs: `/mingw32` and `/mingw64`. They do not match the POSIX standard. The following `grep` calls check these paths:
100100
{line-numbers: true, format: Bash}
101101
```
102102
grep -Rl "General Public License" /mingw32/share/doc
103103
grep -Rl "General Public License" /mingw64/share
104104
```
105105

106-
You can find applications with other licenses than GNU General Public License. This is the list of licenses and possible lines for searching:
106+
You can find applications with other licenses than GNU General Public License. Here is the list of licenses and corresponding phrases for searching:
107107

108108
* MIT - "MIT license"
109109
* Apache - "Apache license"
110110
* BSD - "BSD license"
111111

112112
##### Exercise 2-6. Operations with files and directories
113113

114-
First, you should create directories for saving photos by each year and month. The following commands do this task:
114+
First, you should create directories for saving photos. Each directory should match a specific month of the year. The following commands create them:
115115
{line-numbers: true, format: Bash}
116116
```
117117
mkdir -p ~/photo/2019/11
118118
mkdir -p ~/photo/2019/12
119119
mkdir -p ~/photo/2020/01
120120
```
121121

122-
Suppose that the `D:\Photo` directory contains all photos. You can use the `find` utility for searching files with a creation date equals to November 2019. The `-newermt` option of the utility checks the creation date. Here is an example command:
122+
Suppose that the `D:\Photo` directory contains all your photos. You can use the `find` utility to search photos created in November 2019. The `-newermt` option of the utility checks the creation date. Here is an example command of how to use it:
123123
{line-numbers: false, format: Bash}
124124
```
125125
find /d/Photo -type f -newermt 2019-11-01 ! -newermt 2019-12-01
126126
```
127127

128-
This command looks for files in the `/d/Photo` directory. It corresponds to the `D:\Photo` path in the Windows environment.
128+
This command looks for files in the `/d/Photo` directory. It matches the `D:\Photo` path in the Windows environment.
129129

130-
The first expression `-newermt 2019-11-01` means to search for files changed since November 1, 2019. The second expression `! -newermt 2019-12-01` excludes files modified since December 1, 2019. The exclamation point before the expression is a negation. There is no condition between expressions. But the find utility inserts the logical AND by default. The resulting expression looks like: "files created after November 1, 2019, but no later than November 30, 2019". It means "files for November".
130+
The first expression `-newermt 2019-11-01` points to files changed since November 1, 2019. The second expression `! -newermt 2019-12-01` excludes files modified since December 1, 2019. The exclamation point before the expression is a negation. There is no condition between expressions. The `find` utility inserts the logical AND by default. The resulting expression looks like: "files created after November 1, 2019, but no later than November 30, 2019". It means "the files created in November 2019".
131131

132-
The file search command is ready. Now add the copy action to it. The result looks like this:
132+
The file search command is ready. Now we should add the copy action there. The result looks like this:
133133
{line-numbers: false, format: Bash}
134134
```
135135
find /d/Photo -type f -newermt 2019-11-01 ! -newermt 2019-12-01 -exec cp {} ~/photo/2019/11 \;
136136
```
137137

138-
This command copies the November 2019 files into the `~/photo/2019/11` directory.
138+
This command copies the files created in November 2019 into the `~/photo/2019/11` directory.
139139

140-
Here are similar commands for copying the December and January files:
140+
Here are the similar commands for copying the December and January files:
141141
{line-numbers: true, format: Bash}
142142
```
143143
find /d/Photo -type f -newermt 2019-12-01 ! -newermt 2020-01-01 -exec cp {} ~/photo/2019/12 \;
144144
find /d/Photo -type f -newermt 2020-01-01 ! -newermt 2020-02-01 -exec cp {} ~/photo/2020/01 \;
145145
```
146146

147-
Let's assume that you do not need old files in the `D:\Photo` directory. Then replace copying action with renaming. The result is the following commands:
147+
Let's assume that you do not need old files in the `D:\Photo` directory. Then you should replace the copying action with renaming. This way, you get the following commands:
148148
{line-numbers: true, format: Bash}
149149
```
150150
find /d/Photo -type f -newermt 2019-11-01 ! -newermt 2019-12-01 -exec mv {} ~/photo/2019/11 \;
151151
find /d/Photo -type f -newermt 2019-12-01 ! -newermt 2020-01-01 -exec mv {} ~/photo/2019/12 \;
152152
find /d/Photo -type f -newermt 2020-01-01 ! -newermt 2020-02-01 -exec mv {} ~/photo/2020/01 \;
153153
```
154154

155-
Note the scalability of our solution. The number of files in the `D:\Photo` directory is not important. You need only three commands to break them up into three months.
155+
Note the scalability of our solution. The number of files in the `D:\Photo` directory does not matter. You need only three commands to process them.
156156

157157
##### Exercise 2-7. Pipelines and I/O streams redirection
158158

159-
First, let's figure out how the `bsdtar` utility works. Call it with the `--help` option. It shows you a brief help. The help tells you that the utility archives the directory if you apply the `-c` and `-f` options. The name of the archive follows the options. Here is an example call of the `bsdtar` utility:
159+
First, let's figure out how the `bsdtar` utility works. Call it with the `--help` option. It shows you a brief help. The help tells you that the utility archives a target directory if you apply the `-c` and `-f` options. You should specify the archive name after these options. Here is an example call of the `bsdtar` utility:
160160
{line-numbers: false, format: Bash}
161161
```
162162
bsdtar -c -f test.tar test
163163
```
164164

165-
This command creates an archive named `test.tar`. It has the contents of the `test` directory inside. Note that the command does not [compress data](https://en.wikipedia.org/wiki/Data_compression). It means that the archive occupies the same disk space as the files it contains.
165+
This command creates the `test.tar` archive. It includes the contents of the `test` directory. Note that the command does not [compress data](https://en.wikipedia.org/wiki/Data_compression). It means that the archive occupies the same disk space as the files it contains.
166166

167-
The purposes of archiving and compression operations are different. Archiving is for storing and copying large numbers of files. Compression reduces the amount of the occupied disk memory. Often these operations are combined into one. But they are not the same.
167+
The purposes of archiving and compression operations differ. You need archiving for storing and copying a large number of files. Compression reduces the amount of the occupied disk memory. These operations are combined into one often, but they are not the same.
168168

169-
To create an archive and compress it, add the `-j` option to the `bsdtar` call. Here is an example:
169+
Suppose that you want to create an archive and compress it. Then you need to add the `-j` option to the `bsdtar` call. Here is an example:
170170
{line-numbers: false, format: Bash}
171171
```
172172
bsdtar -c -j -f test.tar.bz2 test
@@ -178,37 +178,37 @@ You can combine the `-c`, `-j` and `-f` options into one group. Then you get the
178178
bsdtar -cjf test.tar.bz2 test
179179
```
180180

181-
Let's write a command to navigate through the catalog of photos. It should create a separate archive for each month.
181+
Let's write a command for processing all photos. The command should archive each directory with the photos of the specific month.
182182

183-
The following `find` utility call finds directories that match specific months:
183+
First, you need to find the directories for archiving. The following command does it:
184184
{line-numbers: false, format: Bash}
185185
```
186186
find ~/photo -type d -path */2019/* -o -path */2020/*
187187
```
188188

189-
Next, we redirect the output of this command to the `xargs` utility. It will generate the `bsdtar` call. Our command looks like this now:
189+
Next, you redirect the output of the `find` call to the `xargs` utility. It will generate the `bsdtar` call. This way, you get the following command:
190190
{line-numbers: false, format: Bash}
191191
```
192192
find ~/photo -type d -path */2019/* -o -path */2020/* | xargs -I% bsdtar -cf %.tar %
193193
```
194194

195-
We can add the `-j` option to force `bsdtar` to compress archived data. The command became like this:
195+
You can add the `-j` option to force `bsdtar` to compress archived data. The command became like this:
196196
{line-numbers: false, format: Bash}
197197
```
198198
find ~/photo -type d -path */2019/* -o -path */2020/* | xargs -I% bsdtar -cjf %.tar.bz2 %
199199
```
200200

201-
I> The data compression takes longer than archiving.
201+
I> The data compression usually takes longer than archiving.
202202

203-
We pass the `-I` parameter to the `xargs` utility. It specifies where to insert the arguments into the generated command. There are two such places in the `bsdtar` utility call: the archive's name and the directory's path to be processed.
203+
We pass the `-I` parameter to the `xargs` utility. It specifies the place to insert the arguments into the generated command. There are two such places in the `bsdtar` utility call: the archive's name and the directory's path to be processed.
204204

205-
Do not forget about filenames with line breaks. To process them correctly, add the `-print0` option to the `find` utility call. This way, we get the following command:
205+
Do not forget about filenames with line breaks. To process them correctly, add the `-print0` option to the `find` call. This way, you get the following command:
206206
{line-numbers: false, format: Bash}
207207
```
208208
find ~/photo -type d -path */2019/* -o -path */2020/* -print0 | xargs -0 -I% bsdtar -cjf %.tar.bz2 %
209209
```
210210

211-
Suppose that we want to keep the files in the archives without relative paths (e.g. `2019/11`). The `--strip-components` option of `bsdtar` removes them. Here is the command with this option:
211+
Suppose that you want to keep the files in the archives without relative paths (e.g. `2019/11`). The `--strip-components` option of `bsdtar` removes them. The following command uses this option:
212212
{line-numbers: false, format: Bash}
213213
```
214214
find ~/photo -type d -path */2019/* -o -path */2020/* -print0 | xargs -0 -I% bsdtar --strip-components=3 -cjf %.tar.bz2 %
@@ -222,87 +222,89 @@ Let's implement the algorithm step by step. The first action is to copy the `REA
222222
cp /usr/share/doc/bash/README ~
223223
```
224224

225-
Use the && operator and the `echo` command to print the command's result into the log file. The command became like this:
225+
Apply the && operator and the `echo` built-in to print the `cp` result into the log file. Then you get the following command:
226226
{line-numbers: false, format: Bash}
227227
```
228228
cp /usr/share/doc/bash/README ~ && echo "cp - OK" > result.log
229229
```
230230

231-
Call the `bsdtar` or `tar` utility to archive a file. Here is an example:
231+
The second step is archiving the file. You can call the `bsdtar` or `tar` utility for that. Here is an example:
232232
{line-numbers: false, format: Bash}
233233
```
234234
bsdtar -cjf ~/README.tar.bz2 ~/README
235235
```
236236

237-
We can print the result of archiving operation using the `echo` command again:
237+
Add `echo` built-in to print the result of the archiving utility. The command becomes like this:
238238
{line-numbers: false, format: Bash}
239239
```
240240
bsdtar -cjf ~/README.tar.bz2 ~/README && echo "bsdtar - OK" >> result.log
241241
```
242242

243-
In this case, the `echo` command appends a line to the end of the existing log file.
243+
Here the `echo` command appends the string to the end of the existing log file.
244244

245-
Let's combine the `cp` and `bsdtar` calls into one command. We should call the `bsdtar` utility only if the `README` file has been successfully copied. To achieve this dependency, we put the && operator between the commands. We get the following command:
245+
Let's combine the `cp` and `bsdtar` utilities into one command. You should call `bsdtar` only if the `README` file has been copied successfully. To achieve this dependency, put the && operator between the calls. This way, you get the following command:
246246
{line-numbers: false, format: Bash}
247247
```
248248
cp /usr/share/doc/bash/README ~ && echo "cp - OK" > result.log && bsdtar -cjf ~/README.tar.bz2 ~/README && echo "bsdtar - OK" >> result.log
249249
```
250250

251-
The last missing step is deleting the `README` file. We can add it this way:
251+
The last step is deleting the `README` file. Do it by the `rm` call this way:
252252
{line-numbers: false, format: Bash}
253253
```
254254
cp /usr/share/doc/bash/README ~ && echo "cp - OK" > ~/result.log && bsdtar -cjf ~/README.tar.bz2 ~/README && echo "bsdtar - OK" >> ~/result.log && rm ~/README && echo "rm - OK" >> ~/result.log
255255
```
256256

257-
Run this command. If it succeeds, the log file looks like this:
257+
Run this command in your terminal. If it succeeds, you get the following log file:
258258
{line-numbers: true}
259259
```
260260
cp - OK
261261
bsdtar - OK
262262
rm - OK
263263
```
264264

265-
The command with calls to three utilities in a row looks cumbersome. It is inconvenient to read and edit. Let's break the command into lines. There are several ways to do this.
265+
The current version of our command calls three utilities in a row. It looks cumbersome and inconvenient for reading. Let's break the command into lines. There are several ways to do that.
266266

267-
The first way is to break lines after logical operators. We apply it and get the following:
267+
The first way is to break lines after logical operators. If you apply this approach, you get the following result:
268268
{line-numbers: true, format: Bash}
269269
```
270270
cp /usr/share/doc/bash/README ~ && echo "cp - OK" > ~/result.log &&
271271
bsdtar -cjf ~/README.tar.bz2 ~/README && echo "bsdtar - OK" >> ~/result.log &&
272272
rm ~/README && echo "rm - OK" >> ~/result.log
273273
```
274274

275-
Try to copy this command into a terminal window and execute it. It will run without errors.
275+
Copy this command to your terminal and execute it. It works properly.
276276

277-
The second way to add line breaks is to use the backslash character. Put a line break right after it. Use this method when there are no logical operators in the command.
277+
The second way to add line breaks is to use the backslash symbol. Put a line break right after it. This method fits well when there are no logical operators in the command.
278278

279-
For example, let's put backslashes before the && operators in our command. Then we get this result:
279+
For example, you can put backslashes before the && operators in our command. Then you get this result:
280280
{line-numbers: true, format: Bash}
281281
```
282282
cp /usr/share/doc/bash/README ~ && echo "cp - OK" > ~/result.log \
283283
&& bsdtar -cjf ~/README.tar.bz2 ~/README && echo "bsdtar - OK" >> ~/result.log \
284284
&& rm ~/README && echo "rm - OK" >> ~/result.log
285285
```
286286

287+
Run this command in your terminal. It works properly too.
288+
287289
## Bash Scrips
288290

289291
##### Exercise 3-2. The full form of parameter expansion
290292

291-
The `find` utility searches for files recursively. It starts from the specified path and passes through all subdirectories. Use the `-maxdepth` option to exclude subdirectories from the search.
293+
The `find` utility searches for files recursively. It starts from the specified path and passes through all subdirectories. If you want to exclude subdirectories from the search, apply the `-maxdepth` option.
292294

293-
The command for searching TXT files in the current directory looks like this:
295+
Here is the command for searching TXT files in the current directory:
294296
{line-numbers: false, format: Bash}
295297
```
296298
find . -maxdepth 1 -type f -name "*.txt"
297299
```
298300

299-
Let's add an action to copy the found files to the user's home directory. The command became like this:
301+
Let's add an action to copy the found files to the user's home directory. The command becomes like this:
300302
{line-numbers: false, format: Bash}
301303
```
302304
find . -maxdepth 1 -type f -name "*.txt" -exec cp -t ~ {} \;
303305
```
304306

305-
Now create a script and name it `txt-copy.sh`. Copy our `find` call into the file.
307+
Now create a script and name it `txt-copy.sh`. Copy our `find` call to this file.
306308

307309
The script should receive an input parameter. The parameter defines an action to apply for each found file. There are two possible actions: copy or move. It is convenient to pass the utility's name as a parameter. Thus, it can be `cp` or `mv`. The script will call the utility by its name.
308310

0 commit comments

Comments
 (0)