<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>文件</title>
<meta name="generator" content="Org mode" />
<meta name="author" content="Wu, Shanliang" />
<style type="text/css">
 <!--/*--><![CDATA[/*><!--*/
  .title  { text-align: center;
             margin-bottom: .2em; }
  .subtitle { text-align: center;
              font-size: medium;
              font-weight: bold;
              margin-top:0; }
  .todo   { font-family: monospace; color: red; }
  .done   { font-family: monospace; color: green; }
  .priority { font-family: monospace; color: orange; }
  .tag    { background-color: #eee; font-family: monospace;
            padding: 2px; font-size: 80%; font-weight: normal; }
  .timestamp { color: #bebebe; }
  .timestamp-kwd { color: #5f9ea0; }
  .org-right  { margin-left: auto; margin-right: 0px;  text-align: right; }
  .org-left   { margin-left: 0px;  margin-right: auto; text-align: left; }
  .org-center { margin-left: auto; margin-right: auto; text-align: center; }
  .underline { text-decoration: underline; }
  #postamble p, #preamble p { font-size: 90%; margin: .2em; }
  p.verse { margin-left: 3%; }
  pre {
    border: 1px solid #ccc;
    box-shadow: 3px 3px 3px #eee;
    padding: 8pt;
    font-family: monospace;
    overflow: auto;
    margin: 1.2em;
  }
  pre.src {
    position: relative;
    overflow: visible;
    padding-top: 1.2em;
  }
  pre.src:before {
    display: none;
    position: absolute;
    background-color: white;
    top: -10px;
    right: 10px;
    padding: 3px;
    border: 1px solid black;
  }
  pre.src:hover:before { display: inline;}
  /* Languages per Org manual */
  pre.src-asymptote:before { content: 'Asymptote'; }
  pre.src-awk:before { content: 'Awk'; }
  pre.src-C:before { content: 'C'; }
  /* pre.src-C++ doesn't work in CSS */
  pre.src-clojure:before { content: 'Clojure'; }
  pre.src-css:before { content: 'CSS'; }
  pre.src-D:before { content: 'D'; }
  pre.src-ditaa:before { content: 'ditaa'; }
  pre.src-dot:before { content: 'Graphviz'; }
  pre.src-calc:before { content: 'Emacs Calc'; }
  pre.src-emacs-lisp:before { content: 'Emacs Lisp'; }
  pre.src-fortran:before { content: 'Fortran'; }
  pre.src-gnuplot:before { content: 'gnuplot'; }
  pre.src-haskell:before { content: 'Haskell'; }
  pre.src-hledger:before { content: 'hledger'; }
  pre.src-java:before { content: 'Java'; }
  pre.src-js:before { content: 'Javascript'; }
  pre.src-latex:before { content: 'LaTeX'; }
  pre.src-ledger:before { content: 'Ledger'; }
  pre.src-lisp:before { content: 'Lisp'; }
  pre.src-lilypond:before { content: 'Lilypond'; }
  pre.src-lua:before { content: 'Lua'; }
  pre.src-matlab:before { content: 'MATLAB'; }
  pre.src-mscgen:before { content: 'Mscgen'; }
  pre.src-ocaml:before { content: 'Objective Caml'; }
  pre.src-octave:before { content: 'Octave'; }
  pre.src-org:before { content: 'Org mode'; }
  pre.src-oz:before { content: 'OZ'; }
  pre.src-plantuml:before { content: 'Plantuml'; }
  pre.src-processing:before { content: 'Processing.js'; }
  pre.src-python:before { content: 'Python'; }
  pre.src-R:before { content: 'R'; }
  pre.src-ruby:before { content: 'Ruby'; }
  pre.src-sass:before { content: 'Sass'; }
  pre.src-scheme:before { content: 'Scheme'; }
  pre.src-screen:before { content: 'Gnu Screen'; }
  pre.src-sed:before { content: 'Sed'; }
  pre.src-sh:before { content: 'shell'; }
  pre.src-sql:before { content: 'SQL'; }
  pre.src-sqlite:before { content: 'SQLite'; }
  /* additional languages in org.el's org-babel-load-languages alist */
  pre.src-forth:before { content: 'Forth'; }
  pre.src-io:before { content: 'IO'; }
  pre.src-J:before { content: 'J'; }
  pre.src-makefile:before { content: 'Makefile'; }
  pre.src-maxima:before { content: 'Maxima'; }
  pre.src-perl:before { content: 'Perl'; }
  pre.src-picolisp:before { content: 'Pico Lisp'; }
  pre.src-scala:before { content: 'Scala'; }
  pre.src-shell:before { content: 'Shell Script'; }
  pre.src-ebnf2ps:before { content: 'ebfn2ps'; }
  /* additional language identifiers per "defun org-babel-execute"
       in ob-*.el */
  pre.src-cpp:before  { content: 'C++'; }
  pre.src-abc:before  { content: 'ABC'; }
  pre.src-coq:before  { content: 'Coq'; }
  pre.src-groovy:before  { content: 'Groovy'; }
  /* additional language identifiers from org-babel-shell-names in
     ob-shell.el: ob-shell is the only babel language using a lambda to put
     the execution function name together. */
  pre.src-bash:before  { content: 'bash'; }
  pre.src-csh:before  { content: 'csh'; }
  pre.src-ash:before  { content: 'ash'; }
  pre.src-dash:before  { content: 'dash'; }
  pre.src-ksh:before  { content: 'ksh'; }
  pre.src-mksh:before  { content: 'mksh'; }
  pre.src-posh:before  { content: 'posh'; }
  /* Additional Emacs modes also supported by the LaTeX listings package */
  pre.src-ada:before { content: 'Ada'; }
  pre.src-asm:before { content: 'Assembler'; }
  pre.src-caml:before { content: 'Caml'; }
  pre.src-delphi:before { content: 'Delphi'; }
  pre.src-html:before { content: 'HTML'; }
  pre.src-idl:before { content: 'IDL'; }
  pre.src-mercury:before { content: 'Mercury'; }
  pre.src-metapost:before { content: 'MetaPost'; }
  pre.src-modula-2:before { content: 'Modula-2'; }
  pre.src-pascal:before { content: 'Pascal'; }
  pre.src-ps:before { content: 'PostScript'; }
  pre.src-prolog:before { content: 'Prolog'; }
  pre.src-simula:before { content: 'Simula'; }
  pre.src-tcl:before { content: 'tcl'; }
  pre.src-tex:before { content: 'TeX'; }
  pre.src-plain-tex:before { content: 'Plain TeX'; }
  pre.src-verilog:before { content: 'Verilog'; }
  pre.src-vhdl:before { content: 'VHDL'; }
  pre.src-xml:before { content: 'XML'; }
  pre.src-nxml:before { content: 'XML'; }
  /* add a generic configuration mode; LaTeX export needs an additional
     (add-to-list 'org-latex-listings-langs '(conf " ")) in .emacs */
  pre.src-conf:before { content: 'Configuration File'; }

  table { border-collapse:collapse; }
  caption.t-above { caption-side: top; }
  caption.t-bottom { caption-side: bottom; }
  td, th { vertical-align:top;  }
  th.org-right  { text-align: center;  }
  th.org-left   { text-align: center;   }
  th.org-center { text-align: center; }
  td.org-right  { text-align: right;  }
  td.org-left   { text-align: left;   }
  td.org-center { text-align: center; }
  dt { font-weight: bold; }
  .footpara { display: inline; }
  .footdef  { margin-bottom: 1em; }
  .figure { padding: 1em; }
  .figure p { text-align: center; }
  .inlinetask {
    padding: 10px;
    border: 2px solid gray;
    margin: 10px;
    background: #ffffcc;
  }
  #org-div-home-and-up
   { text-align: right; font-size: 70%; white-space: nowrap; }
  textarea { overflow-x: auto; }
  .linenr { font-size: smaller }
  .code-highlighted { background-color: #ffff00; }
  .org-info-js_info-navigation { border-style: none; }
  #org-info-js_console-label
    { font-size: 10px; font-weight: bold; white-space: nowrap; }
  .org-info-js_search-highlight
    { background-color: #ffff00; color: #000000; font-weight: bold; }
  .org-svg { width: 90%; }
  /*]]>*/-->
</style>
<link rel="stylesheet" type="text/css" href="../css/main.css" />
<script type="text/javascript">
/*
@licstart  The following is the entire license notice for the
JavaScript code in this tag.

Copyright (C) 2012-2019 Free Software Foundation, Inc.

The JavaScript code in this tag is free software: you can
redistribute it and/or modify it under the terms of the GNU
General Public License (GNU GPL) as published by the Free Software
Foundation, either version 3 of the License, or (at your option)
any later version.  The code is distributed WITHOUT ANY WARRANTY;
without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE.  See the GNU GPL for more details.

As additional permission under GNU GPL version 3 section 7, you
may distribute non-source (e.g., minimized or compacted) forms of
that code without the copy of the GNU GPL normally required by
section 4, provided you include this license notice and a URL
through which recipients can access the Corresponding Source.


@licend  The above is the entire license notice
for the JavaScript code in this tag.
*/
<!--/*--><![CDATA[/*><!--*/
 function CodeHighlightOn(elem, id)
 {
   var target = document.getElementById(id);
   if(null != target) {
     elem.cacheClassElem = elem.className;
     elem.cacheClassTarget = target.className;
     target.className = "code-highlighted";
     elem.className   = "code-highlighted";
   }
 }
 function CodeHighlightOff(elem, id)
 {
   var target = document.getElementById(id);
   if(elem.cacheClassElem)
     elem.className = elem.cacheClassElem;
   if(elem.cacheClassTarget)
     target.className = elem.cacheClassTarget;
 }
/*]]>*///-->
</script>
</head>
<body>
<div id="org-div-home-and-up">
 <a accesskey="h" href="operation-objects.html"> UP </a>
 |
 <a accesskey="H" href="../elisp.html"> HOME </a>
</div><div id="content">
<h1 class="title">文件</h1>
<div id="table-of-contents">
<h2>Table of Contents</h2>
<div id="text-table-of-contents">
<ul>
<li><a href="#org760b7c8">打开文件</a></li>
<li><a href="#org53d8f23">文件读写</a></li>
<li><a href="#org90be9ba">文件信息</a></li>
<li><a href="#orgf9e4cd2">修改文件信息</a></li>
<li><a href="#orgfb973bd">文件名操作</a></li>
<li><a href="#org649f07e">临时文件</a></li>
<li><a href="#org14afedb">读取目录内容</a></li>
<li><a href="#orgfbd11db">文件Handle</a></li>
</ul>
</div>
</div>
<pre class="example">
  作为一个编辑器，自然文件是最重要的操作对象之一

  这一节要介绍有关文件的一系列命令，比如查找文件，读写文件，文件信息、读取目录、文件名操作等
</pre>
<div id="outline-container-org760b7c8" class="outline-2">
<h2 id="org760b7c8">打开文件</h2>
<div class="outline-text-2" id="text-org760b7c8">
<p>
当打开一个文件时，实际上 emacs 做了很多事情：
</p>
<ul class="org-ul">
<li>把文件名展开成为完整的文件名</li>
<li>判断文件是否存在</li>
<li>判断文件是否可读或者文件大小是否太大</li>
<li>查看文件是否已经打开，是否被锁定</li>
<li>向缓冲区插入文件内容</li>
<li>设置缓冲区的模式</li>
</ul>

<pre class="example">
    这还只是简单的一个步骤，实际情况比这要复杂的多，许多异常需要考虑

    而且为了所有函数的可扩展性，许多变量、handler 和 hook 被加入到文件操作的函数中，使得每一个环节都可以让用户或者 elisp 开发者可以定制，甚至完全接管所有的文件操作
</pre>

<p>
这里需要区分两个概念：文件和缓冲区。它们是两个不同的对象：
</p>
<ul class="org-ul">
<li>文件：是在计算机上可持久保存的信息</li>
<li>缓冲区： Emacs 中包含文件内容信息的对象，在 emacs 退出后就会消失，只有当保存缓冲区之后缓冲区里的内容才写到文件中去</li>
</ul>
</div>
</div>
<div id="outline-container-org53d8f23" class="outline-2">
<h2 id="org53d8f23">文件读写</h2>
<div class="outline-text-2" id="text-org53d8f23">
<p>
打开一个文件的命令是 <span class="underline">find-file</span> : 这命令使一个缓冲区访问某个文件，并让这个缓冲区成为当前缓冲区
</p>
<ul class="org-ul">
<li><span class="underline">find-file-noselect</span> ：所有访问文件的核心函数，它只返回访问文件的缓冲区</li>
<li>find-file 在打开文件过程中会调用 <span class="underline">find-file-hook</span></li>
</ul>

<p>
这两个函数都有一个特点，如果 emacs 里已经有一个缓冲区访问这个文件的话，emacs 不会创建另一个缓冲区来访问文件，而只是简单返回或者转到这个缓冲区
</p>

<pre class="example">
    怎样检查有没有缓冲区是否访问某个文件呢？

    所有和文件关联的缓冲区里都有一个 buffer-local 变量buffer-file-name。但是不要直接设置这个变量来改变缓冲区关联的文件，而是使用 set-visited-file-name 来修改

    同样不要直接从 buffer-list 里搜索buffer-file-name 来查找和某个文件关联的缓冲区，应该使用get-file-buffer 或者 find-buffer-visiting
</pre>

<div class="org-src-container">
<pre class="src src-lisp">(find-file <span style="color: #deb887;">"~/tmp/test.txt"</span>)
(<span style="color: #00bfff; font-weight: bold;">with-current-buffer</span>
    (find-file-noselect <span style="color: #deb887;">"~/tmp/test.txt"</span>)
  buffer-file-name)                     <span style="color: #5f9ea0; font-style: italic;">; =&gt; "/home/klose/tmp/test.txt"</span>
(find-buffer-visiting <span style="color: #deb887;">"~/tmp/test.txt"</span>) <span style="color: #5f9ea0; font-style: italic;">; =&gt; #&lt;buffer test.txt&gt;</span>
(get-file-buffer <span style="color: #deb887;">"~/tmp/test.txt"</span>)      <span style="color: #5f9ea0; font-style: italic;">; =&gt; #&lt;buffer test.txt&gt;</span>
</pre>
</div>

<p>
保存一个文件的过程相对简单一些：
</p>
<ol class="org-ol">
<li>首先创建备份文件</li>
<li>处理文件的位模式</li>
<li>将缓冲区写入文件</li>
</ol>

<p>
保存文件的命令是 <span class="underline">save-buffer</span> 
</p>
<ul class="org-ul">
<li>相当于其它编辑器里 <b>另存为</b> 的命令是 <span class="underline">write-file</span> ，在这个过程中会调用一些函数或者 hook: 
<ul class="org-ul">
<li>write-file-functions 和 write-contents-functions 几乎功能完全相同，都是在写入文件之前运行的函数，如果这些函数中有一个返回了 non-nil 的值， 则会认为文件已经写入了，后面的函数都不会运行，而且也不会使用再调用其它 写入文件的函数
<ul class="org-ul">
<li>这两个变量有一个重要的区别是write-contents-functions 在改变主模式之后会被修改，因为它没有permanent-local 属性，而 write-file-functions 则会仍然保留</li>
</ul></li>
<li>before-save-hook 和 write-file-functions 功能也比较类似，但是这个变量里的函数会逐个执行，不论返回什么值也不会影响后面文件的写入</li>
<li>after-save-hook 是在文件已经写入之后才调用的 hook，它是 save-buffer 最后一个动作</li>
</ul></li>
</ul>

<pre class="example">
    但是实际上在 elisp 编程过程中经常遇到的一个问题是读取一个文件中的内容， 读取完之后并不希望这个缓冲区还留下来

    如果直接用 kill-buffer 可能会把用户打开的文件关闭。而且 find-file-noselect 做的事情实在超出我们的需要

</pre>
<p>
这时可能需要的是更底层的文件读写函数，它们是 <span class="underline">insert-file-contents</span> 和 <span class="underline">write-region</span> ，调用形式分别是：
</p>

<div class="org-src-container">
<pre class="src src-lisp">(insert-file-contents filename <span style="color: #98f5ff;">&amp;optional</span> visit beg end replace)
(write-region start end filename <span style="color: #98f5ff;">&amp;optional</span> append visit lockname mustbenew)
</pre>
</div>
<p>
<span class="underline">insert-file-contents</span> 可以插入文件中指定部分到当前缓冲区中：
</p>
<ul class="org-ul">
<li>如果指定 visit 则会标记缓冲区的修改状态并关联缓冲区到文件，一般是不用的</li>
<li>replace 是指是否要删除缓冲区里其它内容，这比先删除缓冲区其它内容后插入文件内容要快一些，但是一般也用不上</li>
</ul>

<pre class="example">
insert-file-contents 会处理文件的编码，如果不需要解码文件的话，可以用 insert-file-contents-literally 
</pre>

<p>
<span class="underline">write-region</span> 可以把缓冲区中的一部分写入到指定文件中：
</p>
<ul class="org-ul">
<li>如果指定 append 则是添加到文件末尾</li>
<li>visit 参数也会把缓冲区和文件关联</li>
<li>lockname 则是文件锁定的名字</li>
<li>mustbenew 确保文件存在时会要求用户确认操作</li>
</ul>
</div>
</div>
<div id="outline-container-org90be9ba" class="outline-2">
<h2 id="org90be9ba">文件信息</h2>
<div class="outline-text-2" id="text-org90be9ba">
<ul class="org-ul">
<li>文件是否存在可以使用 <span class="underline">file-exists-p</span> 来判断：对于目录和一般文件都可以用这个函数进行判断
<ul class="org-ul">
<li>符号链接只有当 <span class="underline">目标文件</span> 存在时才返回 t</li>
</ul></li>
<li><span class="underline">file-readable-p</span> 、 <span class="underline">file-writable-p</span> ， <span class="underline">file-executable-p</span> 分用来测试用户对文件的权限
<ul class="org-ul">
<li>文件的位模式还可以用 <span class="underline">file-modes</span> 函数得到</li>
</ul></li>
</ul>

<div class="org-src-container">
<pre class="src src-lisp">(file-exists-p <span style="color: #deb887;">"~/tmp/test.txt"</span>)              <span style="color: #5f9ea0; font-style: italic;">; =&gt; t</span>
(file-readable-p <span style="color: #deb887;">"~/tmp/test.txt"</span>)            <span style="color: #5f9ea0; font-style: italic;">; =&gt; t</span>
(file-writable-p <span style="color: #deb887;">"~/tmp/test.txt"</span>)            <span style="color: #5f9ea0; font-style: italic;">; =&gt; t</span>
(file-executable-p <span style="color: #deb887;">"~/tmp/test.txt"</span>)          <span style="color: #5f9ea0; font-style: italic;">; =&gt; nil</span>
(format <span style="color: #deb887;">"%o"</span> (file-modes <span style="color: #deb887;">"~/tmp/test.txt"</span>))   <span style="color: #5f9ea0; font-style: italic;">; =&gt; "644"</span>
</pre>
</div>

<p>
文件类型判断：
</p>
<ul class="org-ul">
<li><span class="underline">file-regular-p</span> : 判断一个文件名是否是一个普通文件（不是目录，命名管道、终端或者其它 IO 设备）</li>
<li><span class="underline">file-directory-p</span>: 判断一个文件名是否一个存在的目录</li>
<li><span class="underline">file-symlink-p</span> : 判断一个文件名是否是一个符号链接
<ul class="org-ul">
<li>当文件名是一个符号链接时会返回 <span class="underline">目标文件名</span></li>
<li>文件的真实名字也就是除去相对链接和符号链接后得到的文件名可以用 <span class="underline">file-truename</span> 得到</li>
</ul></li>
</ul>

<pre class="example">
  事实上每个和文件关联的 buffer 里也有一个缓冲区局部变量 buffer-file-truename 来记录这个文件名
</pre>

<div class="org-src-container">
<pre class="src src-sh">$ ls -l t.txt
lrwxrwxrwx 1 klose klose 8 2007-07-15 15:51 t.txt -&gt; test.txt
</pre>
</div>

<div class="org-src-container">
<pre class="src src-lisp">(file-regular-p <span style="color: #deb887;">"~/tmp/t.txt"</span>)         <span style="color: #5f9ea0; font-style: italic;">; =&gt; t</span>
(file-directory-p <span style="color: #deb887;">"~/tmp/t.txt"</span>)       <span style="color: #5f9ea0; font-style: italic;">; =&gt; nil</span>
(file-symlink-p <span style="color: #deb887;">"~/tmp/t.txt"</span>)         <span style="color: #5f9ea0; font-style: italic;">; =&gt; "test.txt"</span>
(file-truename <span style="color: #deb887;">"~/tmp/t.txt"</span>)          <span style="color: #5f9ea0; font-style: italic;">; =&gt; "/home/klose/tmp/test.txt"</span>
</pre>
</div>

<p>
文件更详细的信息可以用 <span class="underline">file-attributes</span> 函数得到。这个函数类似系统的 stat 命令，返回文件几乎所有的信息，包括 <span class="underline">文件类型</span> ， <span class="underline">用户</span> 和 <span class="underline">组用户</span> ， <span class="underline">访问日期</span> 、 <span class="underline">修改日期</span> 、 <span class="underline">status change 日期</span> 、 <span class="underline">文件大小</span> 、 <span class="underline">文件位模式</span> 、 <span class="underline">inode number</span> 、 <span class="underline">system number</span> &#x2026;..
</p>

<div class="org-src-container">
<pre class="src src-lisp">(<span style="color: #00bfff; font-weight: bold;">defun</span> <span style="color: #daa520; font-weight: bold;">file-stat-type</span> (file <span style="color: #98f5ff;">&amp;optional</span> id-format)
  (car (file-attributes file id-format)))
(<span style="color: #00bfff; font-weight: bold;">defun</span> <span style="color: #daa520; font-weight: bold;">file-stat-name-number</span> (file <span style="color: #98f5ff;">&amp;optional</span> id-format)
  (cadr (file-attributes file id-format)))
(<span style="color: #00bfff; font-weight: bold;">defun</span> <span style="color: #daa520; font-weight: bold;">file-stat-uid</span> (file <span style="color: #98f5ff;">&amp;optional</span> id-format)
  (nth 2 (file-attributes file id-format)))
(<span style="color: #00bfff; font-weight: bold;">defun</span> <span style="color: #daa520; font-weight: bold;">file-stat-gid</span> (file <span style="color: #98f5ff;">&amp;optional</span> id-format)
  (nth 3 (file-attributes file id-format)))
(<span style="color: #00bfff; font-weight: bold;">defun</span> <span style="color: #daa520; font-weight: bold;">file-stat-atime</span> (file <span style="color: #98f5ff;">&amp;optional</span> id-format)
  (nth 4 (file-attributes file id-format)))
(<span style="color: #00bfff; font-weight: bold;">defun</span> <span style="color: #daa520; font-weight: bold;">file-stat-mtime</span> (file <span style="color: #98f5ff;">&amp;optional</span> id-format)
  (nth 5 (file-attributes file id-format)))
(<span style="color: #00bfff; font-weight: bold;">defun</span> <span style="color: #daa520; font-weight: bold;">file-stat-ctime</span> (file <span style="color: #98f5ff;">&amp;optional</span> id-format)
  (nth 6 (file-attributes file id-format)))
(<span style="color: #00bfff; font-weight: bold;">defun</span> <span style="color: #daa520; font-weight: bold;">file-stat-size</span> (file <span style="color: #98f5ff;">&amp;optional</span> id-format)
  (nth 7 (file-attributes file id-format)))
(<span style="color: #00bfff; font-weight: bold;">defun</span> <span style="color: #daa520; font-weight: bold;">file-stat-modes</span> (file <span style="color: #98f5ff;">&amp;optional</span> id-format)
  (nth 8 (file-attributes file id-format)))
(<span style="color: #00bfff; font-weight: bold;">defun</span> <span style="color: #daa520; font-weight: bold;">file-stat-guid-changep</span> (file <span style="color: #98f5ff;">&amp;optional</span> id-format)
  (nth 9 (file-attributes file id-format)))
(<span style="color: #00bfff; font-weight: bold;">defun</span> <span style="color: #daa520; font-weight: bold;">file-stat-inode-number</span> (file <span style="color: #98f5ff;">&amp;optional</span> id-format)
  (nth 10 (file-attributes file id-format)))
(<span style="color: #00bfff; font-weight: bold;">defun</span> <span style="color: #daa520; font-weight: bold;">file-stat-system-number</span> (file <span style="color: #98f5ff;">&amp;optional</span> id-format)
  (nth 11 (file-attributes file id-format)))
(<span style="color: #00bfff; font-weight: bold;">defun</span> <span style="color: #daa520; font-weight: bold;">file-attr-type</span> (attr)
  (car attr))
(<span style="color: #00bfff; font-weight: bold;">defun</span> <span style="color: #daa520; font-weight: bold;">file-attr-name-number</span> (attr)
  (cadr attr))
(<span style="color: #00bfff; font-weight: bold;">defun</span> <span style="color: #daa520; font-weight: bold;">file-attr-uid</span> (attr)
  (nth 2 attr))
(<span style="color: #00bfff; font-weight: bold;">defun</span> <span style="color: #daa520; font-weight: bold;">file-attr-gid</span> (attr)
  (nth 3 attr))
(<span style="color: #00bfff; font-weight: bold;">defun</span> <span style="color: #daa520; font-weight: bold;">file-attr-atime</span> (attr)
  (nth 4 attr))
(<span style="color: #00bfff; font-weight: bold;">defun</span> <span style="color: #daa520; font-weight: bold;">file-attr-mtime</span> (attr)
  (nth 5 attr))
(<span style="color: #00bfff; font-weight: bold;">defun</span> <span style="color: #daa520; font-weight: bold;">file-attr-ctime</span> (attr)
  (nth 6 attr))
(<span style="color: #00bfff; font-weight: bold;">defun</span> <span style="color: #daa520; font-weight: bold;">file-attr-size</span> (attr)
  (nth 7 attr))
(<span style="color: #00bfff; font-weight: bold;">defun</span> <span style="color: #daa520; font-weight: bold;">file-attr-modes</span> (attr)
  (nth 8 attr))
(<span style="color: #00bfff; font-weight: bold;">defun</span> <span style="color: #daa520; font-weight: bold;">file-attr-guid-changep</span> (attr)
  (nth 9 attr))
(<span style="color: #00bfff; font-weight: bold;">defun</span> <span style="color: #daa520; font-weight: bold;">file-attr-inode-number</span> (attr)
  (nth 10 attr))
(<span style="color: #00bfff; font-weight: bold;">defun</span> <span style="color: #daa520; font-weight: bold;">file-attr-system-number</span> (attr)
  (nth 11 attr))
</pre>
</div>

<pre class="example">
  前一组函数是直接由文件名访问文件信息，而后一组函数是由 file-attributes 的返回值来得到文件信息
</pre>
</div>
</div>
<div id="outline-container-orgf9e4cd2" class="outline-2">
<h2 id="orgf9e4cd2">修改文件信息</h2>
<div class="outline-text-2" id="text-orgf9e4cd2">
<ul class="org-ul">
<li>重命名和复制文件可以用 <span class="underline">rename-file</span> 和 <span class="underline">copy-file</span></li>
<li>删除文件使用 <span class="underline">delete-file</span></li>
<li>创建目录使用 <span class="underline">make-directory</span> 函数</li>
<li>不能用 delete-file 删除 目录，只能用 <span class="underline">delete-directory</span> 删除目录，当目录不为空时会产生一个错误</li>
<li>设置文件修改时间使用 <span class="underline">set-file-times</span></li>
<li>设置文件位模式可以用 <span class="underline">set-file-modes</span> 函数：参数必须是一个整数
<ul class="org-ul">
<li>可以用位函数 logand、logior 和 logxor 函数来进行位操作</li>
</ul></li>
</ul>
</div>
</div>
<div id="outline-container-orgfb973bd" class="outline-2">
<h2 id="orgfb973bd">文件名操作</h2>
<div class="outline-text-2" id="text-orgfb973bd">
<p>
路径一般由 <span class="underline">目录</span> 和 <span class="underline">文件名</span> ，而文件名一般由 <span class="underline">主文件名</span> (basename)、 <span class="underline">文件名后缀</span> 和 <span class="underline">版本号</span> 构成。 Emacs 有一系列函数来得到路径中的不同部分：
</p>

<div class="org-src-container">
<pre class="src src-lisp">(file-name-directory <span style="color: #deb887;">"~/tmp/test.txt"</span>)      <span style="color: #5f9ea0; font-style: italic;">; =&gt; "~/tmp/"</span>
(file-name-nondirectory <span style="color: #deb887;">"~/tmp/test.txt"</span>)   <span style="color: #5f9ea0; font-style: italic;">; =&gt; "test.txt"</span>
(file-name-sans-extension <span style="color: #deb887;">"~/tmp/test.txt"</span>) <span style="color: #5f9ea0; font-style: italic;">; =&gt; "~/tmp/test"</span>
(file-name-extension <span style="color: #deb887;">"~/tmp/test.txt"</span>)      <span style="color: #5f9ea0; font-style: italic;">; =&gt; "txt"</span>
(file-name-sans-versions <span style="color: #deb887;">"~/tmp/test.txt~"</span>) <span style="color: #5f9ea0; font-style: italic;">; =&gt; "~/tmp/test.txt"</span>
(file-name-sans-versions <span style="color: #deb887;">"~/tmp/test.txt.~1~"</span>) <span style="color: #5f9ea0; font-style: italic;">; =&gt; "~/tmp/test.txt"</span>
</pre>
</div>

<pre class="example">
  虽然 MSWin 的文件名使用的路径分隔符不同，但是这里介绍的函数都能用于 MSWin 形式的文件名，只是返回的文件名都是 Unix 形式了
</pre>

<p>
路径如果是从根目录开始的称为是绝对路径：
</p>
<ul class="org-ul">
<li>测试一个路径是否是绝对路径使用 <span class="underline">file-name-absolute-p</span> 
<ul class="org-ul">
<li>如果在 Unix 或 GNU/Linux 系统，以 ~ 开头的路径也是绝对路径</li>
<li>在 MSWin 上，以 "/" 、 "\"、"X:" 开头的路径都是绝对路径</li>
</ul></li>
<li>如果不是绝对路径，可以使用 <span class="underline">expand-file-name</span> 来得到绝对路径</li>
<li>把一个绝对路径转换成相对某个路径的相对路径的可以用 <span class="underline">file-relative-name</span> 函数</li>
</ul>

<div class="org-src-container">
<pre class="src src-lisp">(file-name-absolute-p <span style="color: #deb887;">"~rms/foo"</span>)       <span style="color: #5f9ea0; font-style: italic;">; =&gt; t</span>
(file-name-absolute-p <span style="color: #deb887;">"/user/rms/foo"</span>)  <span style="color: #5f9ea0; font-style: italic;">; =&gt; t</span>
(expand-file-name <span style="color: #deb887;">"foo"</span>)                <span style="color: #5f9ea0; font-style: italic;">; =&gt; "/home/klose/foo"</span>
(expand-file-name <span style="color: #deb887;">"foo"</span> <span style="color: #deb887;">"/usr/spool/"</span>)  <span style="color: #5f9ea0; font-style: italic;">; =&gt; "/usr/spool/foo"</span>
(file-relative-name <span style="color: #deb887;">"/foo/bar"</span> <span style="color: #deb887;">"/foo/"</span>) <span style="color: #5f9ea0; font-style: italic;">; =&gt; "bar"</span>
(file-relative-name <span style="color: #deb887;">"/foo/bar"</span> <span style="color: #deb887;">"/hack/"</span>) <span style="color: #5f9ea0; font-style: italic;">; =&gt; "../foo/bar"</span>
</pre>
</div>
<p>
对于目录，如果要将其作为目录，也就是确保它是以路径分隔符结束，可以用 <span class="underline">file-name-as-directory</span> 
</p>
<pre class="example">
  不要用 (concat dir "/") 来转换，这会有移植问题
</pre>
<p>
和它相对应的函数是 <span class="underline">directory-file-name</span>
</p>

<div class="org-src-container">
<pre class="src src-lisp">(file-name-as-directory <span style="color: #deb887;">"~rms/lewis"</span>)   <span style="color: #5f9ea0; font-style: italic;">; =&gt; "~rms/lewis/"</span>
(directory-file-name <span style="color: #deb887;">"~lewis/"</span>)         <span style="color: #5f9ea0; font-style: italic;">; =&gt; "~lewis"</span>
</pre>
</div>

<p>
如果要得到所在系统使用的文件名，可以用 <span class="underline">convert-standard-filename</span>
</p>

<div class="org-src-container">
<pre class="src src-lisp">(convert-standard-filename <span style="color: #deb887;">"c:/windows"</span>)  <span style="color: #5f9ea0; font-style: italic;">;=&gt; "c:\\windows"</span>
</pre>
</div>

<pre class="example">
  比如 在 MSWin 系统上，可以用这个函数返回用 "\" 分隔的文件名
</pre>
</div>
</div>
<div id="outline-container-org649f07e" class="outline-2">
<h2 id="org649f07e">临时文件</h2>
<div class="outline-text-2" id="text-org649f07e">
<ul class="org-ul">
<li>如果需要产生一个临时文件，可以使用 <span class="underline">make-temp-file</span>
<ul class="org-ul">
<li>这个函数按给定前缀产生一个不和现有文件冲突的文件，并返回它的文件名</li>
<li>如果给定的名字是一个相对文件名，则产生的文件名会用 <span class="underline">temporary-file-directory</span>  进行扩展
<ul class="org-ul">
<li>也可以用这个函数产生一个临时文件夹</li>
</ul></li>
</ul></li>
<li>如果只想产生一个不存在的文件名，可以用 <span class="underline">make-temp-name</span> 函数</li>
</ul>

<div class="org-src-container">
<pre class="src src-lisp">(make-temp-file <span style="color: #deb887;">"foo"</span>)                  <span style="color: #5f9ea0; font-style: italic;">; =&gt; "/tmp/foo5611dxf"</span>
(make-temp-name <span style="color: #deb887;">"foo"</span>)                  <span style="color: #5f9ea0; font-style: italic;">; =&gt; "foo5611q7l"</span>
</pre>
</div>
</div>
</div>
<div id="outline-container-org14afedb" class="outline-2">
<h2 id="org14afedb">读取目录内容</h2>
<div class="outline-text-2" id="text-org14afedb">
<p>
可以用 <span class="underline">directory-files</span> 来得到某个目录中的全部或者符合某个正则表达式的文件名：
</p>

<div class="org-src-container">
<pre class="src src-lisp">(directory-files <span style="color: #deb887;">"~/tmp/dir/"</span>)
<span style="color: #5f9ea0; font-style: italic;">;; </span><span style="color: #5f9ea0; font-style: italic;">=&gt;</span>
<span style="color: #5f9ea0; font-style: italic;">;; </span><span style="color: #5f9ea0; font-style: italic;">("#foo.el#" "." ".#foo.el" ".." "foo.el" "t.pl" "t2.pl")</span>
(directory-files <span style="color: #deb887;">"~/tmp/dir/"</span> t)
<span style="color: #5f9ea0; font-style: italic;">;; </span><span style="color: #5f9ea0; font-style: italic;">=&gt;</span>
<span style="color: #5f9ea0; font-style: italic;">;; </span><span style="color: #5f9ea0; font-style: italic;">("/home/ywb/tmp/dir/#foo.el#"</span>
<span style="color: #5f9ea0; font-style: italic;">;;  </span><span style="color: #5f9ea0; font-style: italic;">"/home/ywb/tmp/dir/."</span>
<span style="color: #5f9ea0; font-style: italic;">;;  </span><span style="color: #5f9ea0; font-style: italic;">"/home/ywb/tmp/dir/.#foo.el"</span>
<span style="color: #5f9ea0; font-style: italic;">;;  </span><span style="color: #5f9ea0; font-style: italic;">"/home/ywb/tmp/dir/.."</span>
<span style="color: #5f9ea0; font-style: italic;">;;  </span><span style="color: #5f9ea0; font-style: italic;">"/home/ywb/tmp/dir/foo.el"</span>
<span style="color: #5f9ea0; font-style: italic;">;;  </span><span style="color: #5f9ea0; font-style: italic;">"/home/ywb/tmp/dir/t.pl"</span>
<span style="color: #5f9ea0; font-style: italic;">;;  </span><span style="color: #5f9ea0; font-style: italic;">"/home/ywb/tmp/dir/t2.pl")</span>
(directory-files <span style="color: #deb887;">"~/tmp/dir/"</span> nil <span style="color: #deb887;">"\\.pl$"</span>) <span style="color: #5f9ea0; font-style: italic;">; =&gt; ("t.pl" "t2.pl")</span>
</pre>
</div>

<ul class="org-ul">
<li><span class="underline">directory-files-and-attributes</span> 和 directory-files 相似，但是返回的列表 中包含了 file-attributes 得到的信息</li>
<li><span class="underline">file-name-all-versions</span> 用于得到某个文件在目录中的所有版本</li>
<li><span class="underline">file-expand-wildcards</span> 可以用通配符来得到目录中的文件列表</li>
</ul>
</div>
</div>
<div id="outline-container-orgfbd11db" class="outline-2">
<h2 id="orgfbd11db">文件Handle</h2>
<div class="outline-text-2" id="text-orgfbd11db">
<pre class="example">
    如果不把文件局限在存储在本地机器上的信息，而且有一套基本的文件操作，比如判断文件是否存在、打开文件、保存文件、得到目录内容之类，那远程的文件和本地文件的差别也仅在于文件名表示方法不同而已

    在 Emacs 里，底层的文件操作函数都可以托管给 elisp 中的函数，这样只要用 elisp 实现了某种类型文件的基本操作，就能像编辑本地文件一样编辑其它类型文件了
</pre>
<p>
决定何种类型的文件名使用什么方式来操作是在 <span class="underline">file-name-handler-alist</span> 变量定义的。它是由形如 <span class="underline">(REGEXP . HANDLER)</span> 的列表。如果文件名匹配这个 REGEXP 则使用 HANDLER 来进行相应的文件操作。这里所说的文件操作，具体的来说有这些函数：
</p>

<div class="org-src-container">
<pre class="src src-lisp">`<span style="color: #ffd700;">access-file</span>', `<span style="color: #ffd700;">add-name-to-file</span>', `<span style="color: #ffd700;">byte-compiler-base-file-name</span>',
`<span style="color: #ffd700;">copy-file</span>', `<span style="color: #ffd700;">delete-directory</span>', `<span style="color: #ffd700;">delete-file</span>',
`<span style="color: #ffd700;">diff-latest-backup-file</span>', `<span style="color: #ffd700;">directory-file-name</span>', `<span style="color: #ffd700;">directory-files</span>',
`<span style="color: #ffd700;">directory-files-and-attributes</span>', `<span style="color: #ffd700;">dired-call-process</span>',
`<span style="color: #ffd700;">dired-compress-file</span>', `<span style="color: #ffd700;">dired-uncache</span>',
`<span style="color: #ffd700;">expand-file-name</span>', `<span style="color: #ffd700;">file-accessible-directory-p</span>', `<span style="color: #ffd700;">file-attributes</span>',
`<span style="color: #ffd700;">file-directory-p</span>', `<span style="color: #ffd700;">file-executable-p</span>', `<span style="color: #ffd700;">file-exists-p</span>',
`<span style="color: #ffd700;">file-local-copy</span>', `<span style="color: #ffd700;">file-remote-p</span>', `<span style="color: #ffd700;">file-modes</span>',
`<span style="color: #ffd700;">file-name-all-completions</span>', `<span style="color: #ffd700;">file-name-as-directory</span>',
`<span style="color: #ffd700;">file-name-completion</span>', `<span style="color: #ffd700;">file-name-directory</span>', `<span style="color: #ffd700;">file-name-nondirectory</span>',
`<span style="color: #ffd700;">file-name-sans-versions</span>', `<span style="color: #ffd700;">file-newer-than-file-p</span>',
`<span style="color: #ffd700;">file-ownership-preserved-p</span>', `<span style="color: #ffd700;">file-readable-p</span>', `<span style="color: #ffd700;">file-regular-p</span>',
`<span style="color: #ffd700;">file-symlink-p</span>', `<span style="color: #ffd700;">file-truename</span>', `<span style="color: #ffd700;">file-writable-p</span>',
`<span style="color: #ffd700;">find-backup-file-name</span>', `<span style="color: #ffd700;">find-file-noselect</span>',
`<span style="color: #ffd700;">get-file-buffer</span>', `<span style="color: #ffd700;">insert-directory</span>', `<span style="color: #ffd700;">insert-file-contents</span>',
`<span style="color: #ffd700;">load</span>', `<span style="color: #ffd700;">make-auto-save-file-name</span>', `<span style="color: #ffd700;">make-directory</span>',
`<span style="color: #ffd700;">make-directory-internal</span>', `<span style="color: #ffd700;">make-symbolic-link</span>',
`<span style="color: #ffd700;">rename-file</span>', `<span style="color: #ffd700;">set-file-modes</span>', `<span style="color: #ffd700;">set-file-times</span>',
`<span style="color: #ffd700;">set-visited-file-modtime</span>', `<span style="color: #ffd700;">shell-command</span>', `<span style="color: #ffd700;">substitute-in-file-name</span>',
`<span style="color: #ffd700;">unhandled-file-name-directory</span>', `<span style="color: #ffd700;">vc-registered</span>',
`<span style="color: #ffd700;">verify-visited-file-modtime</span>',
`<span style="color: #ffd700;">write-region</span>' 
</pre>
</div>
<p>
在 HANDLE 里，可以只接管部分的文件操作，其它仍交给 emacs 原来的函数来完成
</p>

<pre class="example">
    举一个简单的例子。比如最新版本的 emacs 把 *scratch* 的 auto-save-mode 打开了

    如果你不想这个缓冲区的自动保存的文件名散布得到处都是，可以想办法让这个缓冲区的自动保存文件放到指定的目录中

    刚好 make-auto-save-file-name 是在上面这个列表里的，但是不幸的是在函数定义里 make-auto-save-file-name 里不对不关联文件的缓冲区使用 handler

    继续往下看，发现生成保存文件名是使用了 expand-file-name 函数
</pre>

<p>
一个解决方法就是：
</p>

<div class="org-src-container">
<pre class="src src-lisp">(<span style="color: #00bfff; font-weight: bold;">defun</span> <span style="color: #daa520; font-weight: bold;">my-scratch-auto-save-file-name</span> (operation <span style="color: #98f5ff;">&amp;rest</span> args)
  (<span style="color: #00bfff; font-weight: bold;">if</span> (and (eq operation 'expand-file-name)
           (string= (car args) <span style="color: #deb887;">"#*scratch*#"</span>))
      (expand-file-name (concat <span style="color: #deb887;">"~/.emacs.d/backup/"</span> (car args)))
    (<span style="color: #00bfff; font-weight: bold;">let</span> ((inhibit-file-name-handlers
           (cons 'my-scratch-auto-save-file-name
                 (and (eq inhibit-file-name-operation operation)
                      inhibit-file-name-handlers)))
          (inhibit-file-name-operation operation))
      (apply operation args))))
</pre>
</div>

<p>
<a href="text.html">Next：文本</a>
</p>

<p>
<a href="window.html">Previous：窗口</a>
</p>

<p>
<a href="operation-objects.html">TOP：操作对象</a>
</p>
</div>
</div>
</div>
<div id="postamble" class="status">

		  <br/>
		  <div class='ds-thread'></div>
		  <script>
		  var duoshuoQuery = {short_name:'klose911'};
		  (function() {
					  var dsThread = document.getElementsByClassName('ds-thread')[0];
					  dsThread.setAttribute('data-thread-key', document.title);
					  dsThread.setAttribute('data-title', document.title);
					  dsThread.setAttribute('data-url', window.location.href);
					  var ds = document.createElement('script');
					  ds.type = 'text/javascript';ds.async = true;
					  ds.src = (document.location.protocol == 'https:' ? 'https:' : 'http:') + '//static.duoshuo.com/embed.js';
					  ds.charset = 'UTF-8';
					  (document.getElementsByTagName('head')[0] 
						|| document.getElementsByTagName('body')[0]).appendChild(ds);
					  })();
		  </script>
		  <script>
		  (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
			(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
			m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
			})(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
		  ga('create', 'UA-90850421-1', 'auto');
		  ga('send', 'pageview');
		  </script>
</div>
</body>
</html>
