-- This article comes from TTT blog: http://www.yoyotao.net/ttt/, original address: http://www.yoyotao.net/ttt/post/139.html
Preface:
Although it was a bit of research on batch processing in the past, I have never understood the for command thoroughly. Occasionally, it is also a simple use.
Although this is an antique thing, it is quite interesting and sometimes very useful. Therefore, this time, I decided to study it. I understood 90% through two nights of study and testing, A sense of accomplishment.
During the course of study, I made a detailed summary and explanation, and posted it here for reference by friends who do not understand it. I think it is more understandable than any tutorial, because I never understand it. It is written in conjunction with the process that I never understand ~~ Therefore, it is bold to say that although detailed summary and explanations are made in history ~~
In fact, this study is mainly completed through a highly handwritten tutorial, combined with the help provided by the system. This tutorial is really good, but I forgot to write down the source and author! I searched the internet again just now and found that this tutorial was reposted everywhere. I could not find the author or original source! Thanks to this unknown expert!
-- TTT 200906160033
++
Format: For [parameter] % variable name in (related file or command) Command executed by do
Purpose: execute specific commands on each object in one or more files, strings, or command results to achieve the desired results.
Note: when using the for command in the batch processing file, use % variable instead of % variable to specify the variable. Variable names are case sensitive, so % I is different from % I.
About: The for command can contain or does not contain parameters. The following parameters are supported:/D/L/R/F
The following are two explanations:
===
Zero: No parameter:
---
For % variable in (SET) do command [command-parameters]
% Variable specifies a single letter replaceable parameter.
(SET) specifies one or more files. Wildcard characters can be used.
Command specifies the Command executed on each file.
Command-Parameters
Specify parameters or command line switches for specific commands.
TTT example:
For % I in (T *. *) Do echo % I -- display the file matching T *. * in the current directory (only the file name is displayed, not the path)
For % I In (d:/mydocuments/*. Doc) Do @ echo % I -- display files matching *. doc in the D:/mydocuments/directory
===
1. Parameter/D (the parameter can only display the directory name under the current directory)
---
Format: For/d % variable in (SET) do command [command-parameters]
This parameter is mainly used for Directory Search and does not search for files. The/d parameter can only display the directory name under the current directory. (TTT Special Note: Only the directories under the specified directory will be searched, and no more directories at the next level will be searched .)
TTT example:
For/d % I in (C:/*) Do echo % I -- display all directories under the C root directory
For/d % I in (???) Do echo % I -- display a directory with only 1-3 letters in the current directory
===
2. Parameter/R (search for all files matching the set in the specified path and all subdirectories)
---
Format: For/R [[drive:] path] % variable in (SET) do command [command-parameters]
This command searches for the specified path and all files that match the set in all subdirectories. Note that the path and all subdirectories are specified.
1. If the file name in set contains wildcards (? Or *), lists the directory specified by the/R parameter and all the files that match the set in the subdirectories below it, and the directories that do not match the file are not listed.
2. If set is a specific file name without wildcards, enumerate the directory tree (that is, list the Directory and all its subdirectories) (and add the specific file name to the end ), regardless of whether the specified file in the Set exists.
Example: For/r c:/% I in (*. EXE) Do echo % I -- list the C root directory and all the EXE files under each directory !!!!
TTT example:
For/r c:/% I in (boot. INI) Do echo % I -- enumerate all directories on drive C
For/r d:/backup % I in (1) Do echo % I -- enumeration D/Backup Directory
For/r c:/% I in (boot. INI) do if exist % I echo % I -- a good search command to list directories in Boot. ini
===
3. Parameter/L (this set represents a sequence of numbers from start to end in incremental form. Negative steps can be used)
---
Format: For/L % variable in (START, step, end) do command [command-parameters]
This set indicates a sequence of numbers from start to end in incremental form. You can use a negative step.
TTT example:
For/L % I in (1, 1, 5) Do @ echo % I -- output 1 2 3 4 5
For/L % I in (, 10) Do @ echo % I -- output, 9
For/L % I in (100,-) Do @ echo % I -- output, 80, 60, 40, 20
For/L % I in (, 5) do start cmd -- open five cmd windows
For/L % I in (, 5) Do MD % I -- create from 1 ~ 5. Five folders in total
For/L % I in (1, 1, 5) do RD/Q % I -- delete from 1 ~ 5. Five folders in total
Iv. Parameter/F (Use File Parsing to process command output, strings, and file content .)
---
This parameter is the most difficult and has many parameters. The for command can be used to analyze the file content, string content, or the output result of a command, set the option to get the expected result.
The following is an explanation from a professional who feels a little too professional and thinks it is not easy to understand:
[Iteration and file parsing-Use File Parsing to process command output, strings, and file content. Use iteration variables to define the content or string to be checked, and use various options to further modify the resolution method. Use the options token option to specify which tokens should be passed as iteration variables.
Note: When the token option is not used,/F checks only the first token. The file parsing process includes reading output, string, or file content, dividing it into independent text lines, and parsing each line into zero or more tokens. Then, call the for loop by setting the variable value as the token.
By default,/F passes the first blank separator number of each line of each file. Skip empty rows.]
++
Format:
For/f ["options"] % variable in (file-set) do command [command-parameters]
For/f ["options"] % variable in ("string") do command [command-parameters]
For/f ["options"] % variable in ('command') do command [command-parameters]
Or, if usebackq is available:
For/f ["options"] % variable in (file-set) do command [command-parameters]
For/f ["options"] % variable in ("string") do command [command-parameters]
For/f ["options"] % variable in ('command') do command [command-parameters]
TTT Description: The above is the help content in the WINXP system. You can note that the two are identical, which is actually a system error. The second section "If usebackq option is available:" should be the following:
For/f ["options"] % variable in ("file-set") do command [command-parameters]
For/f ["options"] % variable in ('string') do command [command-parameters]
For/f ["options"] % variable in ('command') do command [command-parameters] -- (the quotation marks in 'command' are backticks, is the key on the left of number 1 on the keyboard)
++
(TTT Description: Below is a detailed explanation. Most of the Help content in the system and some errors (no wonder the for command is so difficult to learn) have been corrected by me .)
1) Explanation of option keywords:
EOL = C: refers to the end of a line comment character (just one ). For example, EOL =; -- ignore the rows headers with semicolons;
Skip = N: the number of lines ignored at the beginning of the file. Example: Skip = 2 -- ignore 2 rows;
Delims = xxx: delimiter set. This replaces the default delimiter set of spaces and the hop key. For example, [delims =,] -- specifies to use commas and spaces to separate strings.
Tokens = x, y, M-N: indicates which symbol of each row is passed to the for itself of each iteration. This leads to the allocation of additional variable names. The M-N format is a range. Use the nth symbol to specify MTH. If the last character in the symbol string is an asterisk, the extra variable will be allocated and accept the reserved Text of the row after the last symbol is parsed. For example: tokens = 2, 3 * -- pass the second and third symbols in each line to the for program body; tokens = 2, 3 *... I % -- the second string obtained is assigned to I %, the third string is assigned to J %, and the remaining string is assigned to K %.
For usebackq, different versions of the system prompt different help, but it is helpful to understand, so the excerpt is as follows:
(1) usebackq: use quotation marks (the key on the left side of number 1 on the keyboard '). If the usebackq parameter is not used, file-set indicates the file. quotation marks are not allowed, so space is not allowed. Double quotation marks are used to indicate the string, that is, String, that is, 'command '. When usebackq is used: Both file-set and "file-set" indicate files. When file paths or names contain spaces, they can be enclosed in double quotation marks. single quotation marks indicate strings, 'string'; quotation marks indicate command execution, that is, 'command '. (This section is the help in WINXP)
(2) usebackq: specify that the new syntax is used in the following situations: execute a string with quotation marks as a command, and a single quotation mark character is a text string command; the file name can be expanded with double quotation marks in filenameset.
The above two items can be understood in combination. I will explain the following:
In fact, this parameter is used to process file names with spaces. If the file name and path you want to process contain spaces, if you use them directly, you will be prompted that the file cannot be found. If you use double quotation marks to enclose the file name and path. At this time, it will be processed as a string instead of a file. This "usebackq" parameter is added to cope with this situation. If this parameter is used, the set of double quotation marks enclosed in brackets can be considered as a file. The real string must be enclosed in single quotation marks. The command must be enclosed in reverse quotation marks.
2) file-set is one or more file names. Before proceeding to the next file in file-set, each file has been opened, read, and processed. Processing includes reading files, dividing them into lines of text, and parsing each line into zero or more symbols. Then, call the for loop with the value of the variable string that has been found. By default,/F uses the first blank symbol separated by each line of each file. Skip blank lines. You can specify the Optional options parameter to replace the default resolution operation. The string with quotation marks contains one or more keywords that specify different resolution options.
3) % I: It is specified in the for statement. % J and % K are specifically described through the tokens = option. You can use tokens = to specify a maximum of 26 characters in a row. If you do not try to illustrate a variable higher than the letter 'Z' or 'Z. Remember that the for variable is a single letter, case sensitive, and global. At the same time, no more than 52 for variables are in use.
(TTT supplement:
Generally, after tokens, only the first parameter is specified, for example, % I or % A. The second and more parameters are used later, and the next parameter is automatically arranged in order. If % A is specified, % B is used to represent the second result, and % C represents the third result... After tokens is tested, multiple variable names are specified. If the test fails, it is not possible. Therefore, you can only use the first variable name after token.
If the variable name used exceeds % Z or % Z, it cannot be used. It was thought that it would be recycled. For example, % A or % A can be used after % Z, however, this is not acceptable after testing.
For example: For/F "tokens = 1, 2, 3 * delims =-," % Y in ("aa bb, CC-dd ee ") do echo % Y % Z % A -- only the first two strings are output, and the other two variables are invalid .)
++
The following is an example provided by the system:
For/F "EOL =; tokens = 2, 3 * delims =," % I in (myfile.txt) Do @ echo % I % J % K --
Note: Each row in myfile.txt is analyzed,
EOL =; -- ignore the rows headers with semicolons;
Tokens = 2, 3 * -- pass the second and third symbols in each line to the for program body;
Delims =, -- Use commas (,) and/or spaces to specify the delimiter.
% I -- The for program body statement references % I to obtain the first string (the second symbol in this example ), reference % J to get the second string (the third symbol in this example) Reference % K to get all the remaining symbols after the third symbol.
(TTT Description: an obvious error in the above examples and descriptions. % I should be replaced with % I (The help has a clear description: Use % variable to specify a variable, instead of using % variable, misleading)
++
TTT: The following are some examples:
1. Example of analysis File
For/F "EOL =; tokens = 1, 2 * delims =,-" % I In (d:/test.txt) Do echo % I % J % K
2. Example of string analysis:
For/F "tokens = 1, 2, 3 * delims =-," % I in ("AA BB, CC-dd ee ") do echo % I % J % K % L
3. Analyze the command output example:
For/F "tokens = 1 * delims =" % I in ('set') Do @ echo [% I ---- % J]
If the usebackq parameter is used, the command is as follows and the result is exactly the same as the preceding one.
1. Example of analysis File
For/F "usebackq EOL =; tokens = 1, 2 * delims =,-" % I in ("D:/test.txt") Do echo % I % J % K
2. Example of string analysis:
For/F "usebackq tokens = 1, 2, 3 * delims =-," % I in ('aa BB, CC-dd ee ') do echo % I % J % K % L
3. Analyze the command output example: (The names and values of environment variables in the current environment are enumerated .)
For/F "usebackq tokens = 1 * delims =" % I in ('set') Do @ echo [% I ---- % J]
You can give it a try and it is easy to understand.
Variables in the for command
---
The replacement of the for variable reference has been enhanced. You can use the following syntax:
~ I-delete any quotation marks (") and expand % I
% ~ Fi-extend % I to a fully qualified path name
% ~ Di-only expand % I to one drive letter
% ~ Pi-only expand % I to one path
% ~ Ni-only expand % I to one file name
% ~ Xi-only expand % I to one file extension
% ~ The SI-extended path contains only short names.
% ~ Ai-extend % I to file attributes
% ~ Ti-extend % I to the date/time of the file
% ~ Zi-expand % I to the file size
% ~ $ Path: I-find the directory of the environment variable in the path (TTT prompt: it is the directory of the PATH environment variable), and expand % I to the first fully qualified name found. If the environment variable name is not defined or the file is not found, the key combination is expanded to an empty string.
In addition, you can combine modifiers to obtain multiple results:
% ~ DPI-only expand % I to one drive letter and Path
% ~ Nxi-only expand % I to one file name and extension
% ~ FSI-only expand % I to a complete path name with a short name
% ~ DP $ path: I-searches the directory of the environment variable in the path and expands % I to the first drive letter and path found.
% ~ Ftzai-extended % I to the Dir similar to the output line
In the preceding example, % I and path can be replaced by other valid values. % ~ Syntax ends with a valid for variable name. Selecting an uppercase variable name similar to % I is easier to read and avoids confusion with case-insensitive key combinations.
(The above is the help of the system)
We can see that each row has an uppercase letter "I", which is actually the variable we bring in for, for example:
For/F "usebackq EOL =; tokens = 1, 2 * delims =,-" % x in ("D:/test.txt") Do echo % x % Y % Z
Here we need to change the X, Y, Z to % ~ FX, % ~ FY, % ~ FZ.
++
TTT exception: The following is a comprehensive example based on the preceding instructions. It can be copied directly to notepad and saved as BAT (any directory in disk C, you can see the expanded results intuitively.
@ Echo off
Echo --- display "dir C:/boot. INI/B/AH"
For/F "delims =" % I in ('dir C:/boot. INI/B/Ah') Do ECHO does not extend the variable % I
For/F "delims =" % I in ('dir C:/boot. INI/B/Ah') Do echo extends the variable ~ FI % ~ Fi-extended to a fully qualified path name
For/F "delims =" % I in ('dir C:/boot. INI/B/Ah') Do echo extends the variable ~ Di % ~ Di -- only extend the variable to one drive letter
For/F "delims =" % I in ('dir C:/boot. INI/B/Ah') Do echo extends the variable ~ Pi % ~ Pi -- only extend the variable to one path
For/F "delims =" % I in ('dir C:/boot. INI/B/Ah') Do echo extends the variable ~ Ni % ~ Ni -- only extend the variable to one file name
For/F "delims =" % I in ('dir C:/boot. INI/B/Ah') Do echo extends the variable ~ XI % ~ XI -- only extend the variable to one file extension
For/F "delims =" % I in ('dir C:/boot. INI/B/Ah') Do echo extends the variable ~ Si % ~ Si -- the expanded path only contains short names
For/F "delims =" % I in ('dir C:/boot. INI/B/Ah') Do echo extends the variable ~ AI % ~ AI -- extend variables to file attributes
For/F "delims =" % I in ('dir C:/boot. INI/B/Ah') Do echo extends the variable ~ Ti % ~ Ti -- extend the variable to the date/time of the file
For/F "delims =" % I in ('dir C:/boot. INI/B/Ah') Do echo extends the variable ~ Zi % ~ Zi -- expand the variable to the file size
For/F "delims =" % I in ('dir C:/boot. INI/B/Ah') Do echo extends the variable ~ $ Path: I % ~ $ Path: I -- find the directory of the environment variable in the path and extend the variable to the first fully qualified name.
Echo --- The following shows the composite modifier to get multiple results ---:
For/F "delims =" % I in ('dir C:/boot. INI/B/Ah') Do echo extends the variable ~ DPI % ~ DPI -- only extend the variable to one drive letter and Path
For/F "delims =" % I in ('dir C:/boot. INI/B/Ah') Do echo extends the variable ~ Nxi % ~ Nxi -- only extend the variable to one file name and extension
For/F "delims =" % I in ('dir C:/boot. INI/B/Ah') Do echo extends the variable ~ FSI % ~ FSI -- only extend the variable to a complete path name with a short name
For/F "delims =" % I in ('dir C:/boot. INI/B/Ah') Do echo extends the variable ~ DP $ path: I % ~ DP $ path: I -- find the directory of the Environment Variable listed in the path, and expand the variable to the first drive letter and path found
For/F "delims =" % I in ('dir C:/boot. INI/B/Ah') Do echo extends the variable ~ Ftzai % ~ Ftzai -- extend the variable to the Dir similar to the output line
Echo.
Echo --- display "dir C:/Windows/system32/notepad.exe/B"
For/F "delims =" % I in ('dir C:/Windows/system32/notepad.exe/B ') Do ECHO does not extend the variable % I
For/F "delims =" % I in ('dir C:/Windows/system32/notepad.exe/B ') Do echo extends the variable ~ FI % ~ Fi-extended to a fully qualified path name
For/F "delims =" % I in ('dir C:/Windows/system32/notepad.exe/B ') Do echo extends the variable ~ Di % ~ Di -- only extend the variable to one drive letter
For/F "delims =" % I in ('dir C:/Windows/system32/notepad.exe/B ') Do echo extends the variable ~ Pi % ~ Pi -- only extend the variable to one path
For/F "delims =" % I in ('dir C:/Windows/system32/notepad.exe/B ') Do echo extends the variable ~ Ni % ~ Ni -- only extend the variable to one file name
For/F "delims =" % I in ('dir C:/Windows/system32/notepad.exe/B ') Do echo extends the variable ~ XI % ~ XI -- only extend the variable to one file extension
For/F "delims =" % I in ('dir C:/Windows/system32/notepad.exe/B ') Do echo extends the variable ~ Si % ~ Si -- the expanded path only contains short names
For/F "delims =" % I in ('dir C:/Windows/system32/notepad.exe/B ') Do echo extends the variable ~ AI % ~ AI -- extend variables to file attributes
For/F "delims =" % I in ('dir C:/Windows/system32/notepad.exe/B ') Do echo extends the variable ~ Ti % ~ Ti -- extend the variable to the date/time of the file
For/F "delims =" % I in ('dir C:/Windows/system32/notepad.exe/B ') Do echo extends the variable ~ Zi % ~ Zi -- expand the variable to the file size
For/F "delims =" % I in ('dir C:/Windows/system32/notepad.exe/B ') Do echo extends the variable ~ $ Path: I % ~ $ Path: I -- find the directory of the environment variable in the path and extend the variable to the first fully qualified name.
Echo --- The following shows the composite modifier to get multiple results ---:
For/F "delims =" % I in ('dir C:/Windows/system32/notepad.exe/B ') Do echo extends the variable ~ DPI % ~ DPI -- only extend the variable to one drive letter and Path
For/F "delims =" % I in ('dir C:/Windows/system32/notepad.exe/B ') Do echo extends the variable ~ Nxi % ~ Nxi -- only extend the variable to one file name and extension
For/F "delims =" % I in ('dir C:/Windows/system32/notepad.exe/B ') Do echo extends the variable ~ FSI % ~ FSI -- only extend the variable to a complete path name with a short name
For/F "delims =" % I in ('dir C:/Windows/system32/notepad.exe/B ') Do echo extends the variable ~ DP $ path: I % ~ DP $ path: I -- find the directory of the Environment Variable listed in the path, and expand the variable to the first drive letter and path found
For/F "delims =" % I in ('dir C:/Windows/system32/notepad.exe/B ') Do echo extends the variable ~ Ftzai % ~ Ftzai -- extend the variable to the Dir similar to the output line
Pause
TTT description:
1. In the preceding command, % ~ FSI cannot be displayed. It is estimated that it is a system error because % ~ FI is extended to a fully qualified path name, % ~ Si only contains short file names, which are in conflict with each other, so an error occurs. I do not know whether it is a system error or test us ~~
2. If the above command is saved in another drive, the correct drive and path cannot be displayed.
3. If you want to % ~ DP $ path: I is displayed normally. Make sure the path of the environment variable is C:/Windows/system32.
The following describes in sequence:
++
I ,~ I-delete any quotation marks (") and extend % I
---
This variable is used to delete quotation marks, as described in his remarks!
The rules for deleting quotation marks are as follows (BAT brother added !) :
1. If both the start and end of a string have quotation marks, the quotation marks at the beginning and end are deleted;
2. If no quotation marks exist at the end of the string, the quotation marks at the beginning of the string are deleted;
3. If there are quotation marks in the middle of the string, or there are quotation marks only at the end of the string, it is not deleted.
Add a tornado: Do not delete headers or even tails.
Let's take a look at this example. First, create the "temp.txt" file. The content is as follows:
1111
"2222"
3333"
"4444" 44
"55" 55 "55
You can also create a BAT file with the following code:
@ Echo off
Echo ^" 1111> temp.txt
Echo "2222"> temp.txt
Echo 3333 ^ "> temp.txt
Echo "4444" 44> temp.txt
Echo ^ "55" 55 "55> temp.txt
Create a temporary file on rem. Note that escape characters are required for unpaired quotation marks ^. Do not leave spaces before the redirection symbol.
For/F "delims =" % I in (temp.txt) Do echo % ~ I
Pause
Del temp.txt
After the command is executed, the echo of CMD is as follows:
1111 # The quotation marks before the string are deleted
2222 # The quotation marks at the beginning and end of the string are deleted
3333 "# No quotation marks before the string, and the quotation marks are retained
4444 "44 # The quotation marks before the string are deleted, while the quotation marks in the middle are retained.
55 "55" 55 # The quotation marks in front of the string are deleted, while the quotation marks in the middle are retained.
Press any key to continue...
When comparing the content in temp.txt, we can see that the quotation marks for lines 1st, 2, and 5 are all removed. This is to delete the quotation marks ~ I's done!
++
Ii. % ~ Fi-extend % I to a fully qualified path name
Example:
Save the Code wherever you are. I will put it on the desktop here.
For/F "delims =" % I in ('dir/B ') Do @ echo % ~ Fi
Pause
The following content is displayed after execution:
C:/Documents and Settings/Administrator/desktop/test. bat
C:/Documents and Settings/Administrator/desktop/test. vbs
When I put % ~ In the code ~ Change fi directly to % I
For/F "delims =" % I in ('dir/B ') Do @ echo % I
Pause
The following content is displayed after execution:
Test. bat
Test. vbs
Through comparison, we can easily see that there is no path, which is the role of "extending % I to a fully qualified path name, that is, if the content of the % I variable is a file name, it will print the absolute path of the file, not just a file name, you can find the manual experiment by yourself!
++
Iii. % ~ Di-extend % I to only one drive letter
Example:
The Code is as follows. I still want to run it on the desktop!
For/F "delims =" % I in ('dir/B ') Do @ echo % ~ Di
Pause
After the command is executed, the following information is displayed in cmd:
C:
C:
My desktop has two files: Test. bat, test. vbs, % ~ Di indicates that if the content of the variable % I is a file or directory name, it prints out the disk symbol of the file or directory!
++
Iv. % ~ Pi-only extend % I to one path
This method is the same as above. It only prints the path and does not print the file name.
For/F "delims =" % I in ('dir/B ') Do @ echo % ~ Pi
Pause
I won't hit the results. Let's copy the code and check the results. The following code is used to show the results!
++
V. % ~ Ni-extends % I to only one file name
Print only the file name
For/F "delims =" % I in ('dir/B ') Do @ echo % ~ Ni
Pause
++
Vi. % ~ Xi-only extend % I to one file extension
Print file extensions only
For/F "delims =" % I in ('dir/B ') Do @ echo % ~ XI
Pause
++
VII. % ~ The SI-extended path contains only short names.
Print absolute short file name
For/F "delims =" % I in ('dir/B ') Do @ echo % ~ Si
Pause
++
VIII. % ~ Ai-extend % I to file attributes
Print file attributes
For/F "delims =" % I in ('dir/B ') Do @ echo % ~ AI
Pause
++
9.% ~ Ti-extend % I to the date/time of the file
Print the date when the file was created
For/F "delims =" % I in ('dir/B ') Do @ echo % ~ Ti
Pause
++
10.% ~ Zi-extend % I to the file size
Print File Size
For/F "delims =" % I in ('dir/B ') Do @ echo % ~ Zi
Pause
Tornado supplement: In the above example, "delims =" can be changed to "delims =", that is, do not use separators.
++
11.% ~ $ Path: I-find the directory of the environment variable in the path and extend % I to the first fully qualified name found. If the environment variable name is not defined or the file is not found, the key combination expands to an empty string.
This is the last one. It is different from those above. Let me talk about it separately!
Save the code as a batch and put it on the desktop.
@ Echo off
For/F "delims =" % I in ({notepad.exe ") do echo % ~ $ Path: I
Pause
Tornado supplement: The above code shows the result of C:/Windows/system32/notepad.exe
The other idea is to search for the notepad.exefile in the path variable. If there is notepad.exe, it will print out the absolute path of the file. If there is no such file, an error will be printed!
(TTT Description: Save it to the desktop. The running result is: the system cannot find the file named notepad.exe ". Check that this path exists in the environment variable path. The reason is unknown! Later I found out why it was originally a Chinese quotation mark.
The above command should be written:
For/F "delims =" % I in ("notepad.exe") Do echo % ~ $ Path: I
)
-- This article comes from TTT blog: http://www.yoyotao.net/ttt/, original address: http://www.yoyotao.net/ttt/post/137.html