📄 special-chars.html
字号:
BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><PRECLASS="PROGRAMLISTING"> 1 #!/bin/bash 2 # uppercase.sh : Changes input to uppercase. 3 4 tr 'a-z' 'A-Z' 5 # Letter ranges must be quoted 6 #+ to prevent filename generation from single-letter filenames. 7 8 exit 0</PRE></TD></TR></TABLE> Now, let us pipe the output of <BCLASS="COMMAND">ls -l</B> to this script. <TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><PRECLASS="SCREEN"> <TTCLASS="PROMPT">bash$ </TT><TTCLASS="USERINPUT"><B>ls -l | ./uppercase.sh</B></TT> <TTCLASS="COMPUTEROUTPUT">-RW-RW-R-- 1 BOZO BOZO 109 APR 7 19:49 1.TXT -RW-RW-R-- 1 BOZO BOZO 109 APR 14 16:48 2.TXT -RW-R--R-- 1 BOZO BOZO 725 APR 20 20:56 DATA-FILE</TT> </PRE></TD></TR></TABLE> </P><DIVCLASS="NOTE"><TABLECLASS="NOTE"WIDTH="90%"BORDER="0"><TR><TDWIDTH="25"ALIGN="CENTER"VALIGN="TOP"><IMGSRC="common/note.png"HSPACE="5"ALT="Note"></TD><TDALIGN="LEFT"VALIGN="TOP"><P>The <TTCLASS="FILENAME">stdout</TT> of each process in a pipe must be read as the <TTCLASS="FILENAME">stdin</TT> of the next. If this is not the case, the data stream will <ICLASS="EMPHASIS">block</I>, and the pipe will not behave as expected. <TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><PRECLASS="PROGRAMLISTING"> 1 cat file1 file2 | ls -l | sort 2 # The output from "cat file1 file2" disappears.</PRE></TD></TR></TABLE> </P><P>A pipe runs as a <AHREF="othertypesv.html#CHILDREF">child process</A>, and therefore cannot alter script variables. <TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><PRECLASS="PROGRAMLISTING"> 1 variable="initial_value" 2 echo "new_value" | read variable 3 echo "variable = $variable" # variable = initial_value</PRE></TD></TR></TABLE> </P><P>If one of the commands in the pipe aborts, this prematurely terminates execution of the pipe. Called a <ICLASS="EMPHASIS">broken pipe</I>, this condition sends a <ICLASS="EMPHASIS">SIGPIPE</I> <AHREF="debugging.html#SIGNALD">signal</A>.</P></TD></TR></TABLE></DIV></DD><DT><SPANCLASS="TOKEN">>|</SPAN></DT><DD><DIVCLASS="FORMALPARA"><P><B>force redirection (even if the <AHREF="options.html#NOCLOBBERREF">noclobber option</A> is set). </B>This will forcibly overwrite an existing file.</P></DIV></DD><DT><SPANCLASS="TOKEN">||</SPAN></DT><DD><DIVCLASS="FORMALPARA"><P><B><AHREF="operations.html#ORREF">OR logical operator</A>. </B>In a <AHREF="tests.html#TESTCONSTRUCTS1">test construct</A>, the <SPANCLASS="TOKEN">||</SPAN> operator causes a return of <SPANCLASS="RETURNVALUE">0</SPAN> (success) if <ICLASS="EMPHASIS">either</I> of the linked test conditions is true.</P></DIV></DD><DT><SPANCLASS="TOKEN">&</SPAN></DT><DD><DIVCLASS="FORMALPARA"><P><B>Run job in background. </B>A command followed by an <SPANCLASS="TOKEN">&</SPAN> will run in the background.</P></DIV><P> <TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><PRECLASS="SCREEN"> <TTCLASS="PROMPT">bash$ </TT><TTCLASS="USERINPUT"><B>sleep 10 &</B></TT> <TTCLASS="COMPUTEROUTPUT">[1] 850</TT> <TTCLASS="COMPUTEROUTPUT">[1]+ Done sleep 10</TT> </PRE></TD></TR></TABLE> </P><P>Within a script, commands and even <AHREF="loops.html#FORLOOPREF1">loops</A> may run in the background.</P><DIVCLASS="EXAMPLE"><HR><ANAME="BGLOOP"></A><P><B>Example 3-3. Running a loop in the background</B></P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><PRECLASS="PROGRAMLISTING"> 1 #!/bin/bash 2 # background-loop.sh 3 4 for i in 1 2 3 4 5 6 7 8 9 10 # First loop. 5 do 6 echo -n "$i " 7 done & # Run this loop in background. 8 # Will sometimes execute after second loop. 9 10 echo # This 'echo' sometimes will not display. 11 12 for i in 11 12 13 14 15 16 17 18 19 20 # Second loop. 13 do 14 echo -n "$i " 15 done 16 17 echo # This 'echo' sometimes will not display. 18 19 # ====================================================== 20 21 # The expected output from the script: 22 # 1 2 3 4 5 6 7 8 9 10 23 # 11 12 13 14 15 16 17 18 19 20 24 25 # Sometimes, though, you get: 26 # 11 12 13 14 15 16 17 18 19 20 27 # 1 2 3 4 5 6 7 8 9 10 bozo $ 28 # (The second 'echo' doesn't execute. Why?) 29 30 # Occasionally also: 31 # 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 32 # (The first 'echo' doesn't execute. Why?) 33 34 # Very rarely something like: 35 # 11 12 13 1 2 3 4 5 6 7 8 9 10 14 15 16 17 18 19 20 36 # The foreground loop preempts the background one. 37 38 exit 0 39 40 # Nasimuddin Ansari suggests adding sleep 1 41 #+ after the echo -n "$i" in lines 6 and 14, 42 #+ for some real fun.</PRE></TD></TR></TABLE><HR></DIV><DIVCLASS="CAUTION"><TABLECLASS="CAUTION"WIDTH="90%"BORDER="0"><TR><TDWIDTH="25"ALIGN="CENTER"VALIGN="TOP"><IMGSRC="common/caution.png"HSPACE="5"ALT="Caution"></TD><TDALIGN="LEFT"VALIGN="TOP"><P>A command run in the background within a script may cause the script to hang, waiting for a keystroke. Fortunately, there is a <AHREF="internal.html#WAITHANG">remedy</A> for this.</P></TD></TR></TABLE></DIV></DD><DT><SPANCLASS="TOKEN">&&</SPAN></DT><DD><DIVCLASS="FORMALPARA"><P><B><AHREF="operations.html#LOGOPS1">AND logical operator</A>. </B>In a <AHREF="tests.html#TESTCONSTRUCTS1">test construct</A>, the <SPANCLASS="TOKEN">&&</SPAN> operator causes a return of <SPANCLASS="RETURNVALUE">0</SPAN> (success) only if <ICLASS="EMPHASIS">both</I> the linked test conditions are true.</P></DIV></DD><DT><ANAME="DASHREF"></A><SPANCLASS="TOKEN">-</SPAN></DT><DD><DIVCLASS="FORMALPARA"><P><B>option, prefix. </B>Option flag for a command or filter. Prefix for an operator.</P></DIV><P><TTCLASS="USERINPUT"><B>COMMAND -[Option1][Option2][...]</B></TT></P><P><TTCLASS="USERINPUT"><B>ls -al</B></TT></P><P><TTCLASS="USERINPUT"><B>sort -dfu $filename</B></TT></P><P><TTCLASS="USERINPUT"><B>set -- $variable</B></TT></P><P> <TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><PRECLASS="PROGRAMLISTING"> 1 if [ $file1 -ot $file2 ] 2 then 3 echo "File $file1 is older than $file2." 4 fi 5 6 if [ "$a" -eq "$b" ] 7 then 8 echo "$a is equal to $b." 9 fi 10 11 if [ "$c" -eq 24 -a "$d" -eq 47 ] 12 then 13 echo "$c equals 24 and $d equals 47." 14 fi</PRE></TD></TR></TABLE> </P></DD><DT><ANAME="DASHREF2"></A><SPANCLASS="TOKEN">-</SPAN></DT><DD><DIVCLASS="FORMALPARA"><P><B>redirection from/to <TTCLASS="FILENAME">stdin</TT> or <TTCLASS="FILENAME">stdout</TT> [dash]. </B><ANAME="COXEX"></A></P></DIV><P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><PRECLASS="PROGRAMLISTING"> 1 (cd /source/directory && tar cf - . ) | (cd /dest/directory && tar xpvf -) 2 # Move entire file tree from one directory to another 3 # [courtesy Alan Cox <a.cox@swansea.ac.uk>, with a minor change] 4 5 # 1) cd /source/directory Source directory, where the files to be moved are. 6 # 2) && "And-list": if the 'cd' operation successful, then execute the next command. 7 # 3) tar cf - . The 'c' option 'tar' archiving command creates a new archive, 8 # the 'f' (file) option, followed by '-' designates the target file as stdout, 9 # and do it in current directory tree ('.'). 10 # 4) | Piped to... 11 # 5) ( ... ) a subshell 12 # 6) cd /dest/directory Change to the destination directory. 13 # 7) && "And-list", as above 14 # 8) tar xpvf - Unarchive ('x'), preserve ownership and file permissions ('p'), 15 # and send verbose messages to stdout ('v'), 16 # reading data from stdin ('f' followed by '-'). 17 # 18 # Note that 'x' is a command, and 'p', 'v', 'f' are options. 19 # Whew! 20 21 22 23 # More elegant than, but equivalent to: 24 # cd source/directory 25 # tar cf - . | (cd ../dest/directory; tar xpvf -) 26 # 27 # Also having same effect: 28 # cp -a /source/directory/* /dest/directory 29 # Or: 30 # cp -a /source/directory/* /source/directory/.[^.]* /dest/directory 31 # If there are hidden files in /source/directory.</PRE></TD></TR></TABLE></P><P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><PRECLASS="PROGRAMLISTING"> 1 bunzip2 linux-2.6.13.tar.bz2 | tar xvf - 2 # --uncompress tar file-- | --then pass it to "tar"-- 3 # If "tar" has not been patched to handle "bunzip2", 4 # this needs to be done in two discrete steps, using a pipe. 5 # The purpose of the exercise is to unarchive "bzipped" kernel source.</PRE></TD></TR></TABLE></P><P>Note that in this context the <SPANCLASS="QUOTE">"-"</SPAN> is not itself a Bash operator, but rather an option recognized by certain UNIX utilities that write to <TTCLASS="FILENAME">stdout</TT>, such as <BCLASS="COMMAND">tar</B>, <BCLASS="COMMAND">cat</B>, etc.</P><P> <TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><PRECLASS="SCREEN"> <TTCLASS="PROMPT">bash$ </TT><TTCLASS="USERINPUT"><B>echo "whatever" | cat -</B></TT> <TTCLASS="COMPUTEROUTPUT">whatever</TT> </PRE></TD></TR></TABLE> </P><P>Where a filename is expected, <TTCLASS="REPLACEABLE"><I>-</I></TT> redirects output to <TTCLASS="FILENAME">stdout</TT> (sometimes seen with <TTCLASS="USERINPUT"><B>tar cf</B></TT>), or accepts input from <TTCLASS="FILENAME">stdin</TT>, rather than from a file. This is a method of using a file-oriented utility as a filter in a pipe.</P><P> <TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><PRECLASS="SCREEN"> <TTCLASS="PROMPT">bash$ </TT><TTCLASS="USERINPUT"><B>file</B></TT> <TTCLASS="COMPUTEROUTPUT">Usage: file [-bciknvzL] [-f namefile] [-m magicfiles] file...</TT> </PRE></TD></TR></TABLE> By itself on the command line, <AHREF="filearchiv.html#FILEREF">file</A> fails with an error message. </P><P> Add a <SPANCLASS="QUOTE">"-"</SPAN> for a more useful result. This causes the shell to await user input. <TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><PRECLASS="SCREEN"> <TTCLASS="PROMPT">bash$ </TT><TTCLASS="USERINPUT"><B>file -</B></TT> <TTCLASS="USERINPUT"><B>abc</B></TT> <TTCLASS="COMPUTEROUTPUT">standard input: ASCII text</TT> <TTCLASS="PROMPT">bash$ </TT><TTCLASS="USERINPUT"><B>file -</B></TT> <TTCLASS="USERINPUT"><B>#!/bin/bash</B></TT> <TTCLASS="COMPUTEROUTPUT">standard input: Bourne-Again shell script text executable</TT> </PRE></TD></TR></TABLE> Now the command accepts input from <TTCLASS="FILENAME">stdin</TT> and analyzes it. </P><P>The <SPANCLASS="QUOTE">"-"</SPAN> can be used to pipe <TTCLASS="FILENAME">stdout</TT> to other commands. This permits such stunts as <AHREF="assortedtips.html#PREPENDREF">prepending lines to a file</A>.</P><P>Using <AHREF="filearchiv.html#DIFFREF">diff</A> to compare a file with a <ICLASS="EMPHASIS">section</I> of another:</P><P><TTCLASS="USERINPUT"><B>grep Linux file1 | diff file2 -</B></TT></P><P>Finally, a real-world example using <TTCLASS="REPLACEABLE"><I>-</I></TT> with <AHREF="filearchiv.html#TARREF">tar</A>.</P><DIVCLASS="EXAMPLE"><HR><ANAME="EX58"></A><P><B>Example 3-4. Backup of all files changed in last day</B></P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><PRECLASS="PROGRAMLISTING"> 1 #!/bin/bash 2 3 # Backs up all files in current directory modified within last 24 hours 4 #+ in a "tarball" (tarred and gzipped file). 5 6 BACKUPFILE=backup-$(date +%m-%d-%Y) 7 # Embeds date in backup filename. 8 # Thanks, Joshua Tschida, for the idea. 9 archive=${1:-$BACKUPFILE} 10 # If no backup-archive filename specified on command line, 11 #+ it will default to "backup-MM-DD-YYYY.tar.gz." 12 13 tar cvf - `find . -mtime -1 -type f -print` > $archive.tar 14 gzip $archive.tar 15 echo "Directory $PWD backed up in archive file \"$archive.tar.gz\"." 16 17 18 # Stephane Chazelas points out that the above code will fail 19 #+ if there are too many files found 20 #+ or if any filenames contain blank characters. 21 22 # He suggests the following alternatives: 23 # ------------------------------------------------------------------- 24 # find . -mtime -1 -type f -print0 | xargs -0 tar rvf "$archive.tar" 25 # using the GNU version of "find". 26 27 28 # find . -mtime -1 -type f -exec tar rvf "$archive.tar" '{}' \; 29 # portable to other UNIX flavors, but much slower. 30 # ------------------------------------------------------------------- 31 32 33 exit 0</PRE></TD></TR></TABLE><HR></DIV><DIVCLASS="CAUTION"><TABLECLASS="CAUTION"WIDTH="90%"BORDER="0"><TR><TDWIDTH="25"ALIGN="CENTER"VALIGN="TOP"><IMGSRC="common/caution.png"HSPACE="5"ALT="Caution"></TD><TDALIGN="LEFT"VALIGN="TOP"><P>Filenames beginning with <SPANCLASS="QUOTE">"-"</SPAN> may cause problems when coupled with the <SPANCLASS="QUOTE">"-"</SPAN> redirection operator. A script should check for this and add an appropriate prefix to such filenames, for example <TTCLASS="FILENAME">./-FILENAME</TT>, <TTCLASS="FILENAME">$PWD/-FILENAME</TT>, or <TTCLASS="FILENAME">$PATHNAME/-FILENAME</TT>.</P><P>If the value of a variable begins with a <TTCLASS="REPLACEABLE"><I>-</I></TT>, this may likewise create problems. <TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><PRECLASS="PROGRAMLISTING"> 1 var="-n" 2 echo $var 3 # Has the effect of "echo -n", and outputs nothing.</PRE></TD></TR></TABLE> </P
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -