diff --git a/Configurations.md b/Configurations.md
index 8540bc36383..0b2048958e1 100644
--- a/Configurations.md
+++ b/Configurations.md
@@ -2135,3 +2135,32 @@ Copyright 2018 The Rust Project Developers.`, etc.:
 ```
 
 `\{`, `\}` and `\\` match literal braces / backslashes.
+
+## `ignore`
+
+Skip formatting the specified files and directories.
+
+- **Default value**: format every files
+- **Possible values**: See an example below
+- **Stable**: No
+
+### Example
+
+If you want to ignore specific files, put the following to your config file:
+
+```toml
+[ignore]
+files = [
+    "src/types.rs",
+    "src/foo/bar.rs",
+]
+```
+
+If you want to ignore every file under `examples/`, put the following to your config file:
+
+```toml
+[ignore]
+directories = [
+    "examples",
+]
+```
diff --git a/src/bin/main.rs b/src/bin/main.rs
index b9d413bbed0..4a49ce5a2e6 100644
--- a/src/bin/main.rs
+++ b/src/bin/main.rs
@@ -18,6 +18,7 @@ use std::{env, error};
 use std::fs::File;
 use std::io::{self, Read, Write};
 use std::path::{Path, PathBuf};
+use std::str::FromStr;
 
 use getopts::{Matches, Options};
 
@@ -25,8 +26,6 @@ use rustfmt::config::{get_toml_path, Color, Config, WriteMode};
 use rustfmt::config::file_lines::FileLines;
 use rustfmt::{run, FileName, Input, Summary};
 
-use std::str::FromStr;
-
 type FmtError = Box<error::Error + Send + Sync>;
 type FmtResult<T> = std::result::Result<T, FmtError>;
 
diff --git a/src/config/config_type.rs b/src/config/config_type.rs
index dc768490fbb..53a4fdb8e57 100644
--- a/src/config/config_type.rs
+++ b/src/config/config_type.rs
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 use config::file_lines::FileLines;
-use config::options::WidthHeuristics;
+use config::options::{IgnoreList, WidthHeuristics};
 
 /// Trait for types that can be used in `Config`.
 pub trait ConfigType: Sized {
@@ -54,6 +54,12 @@ impl ConfigType for WidthHeuristics {
     }
 }
 
+impl ConfigType for IgnoreList {
+    fn doc_hint() -> String {
+        String::from("[<string>,..]")
+    }
+}
+
 /// Check if we're in a nightly build.
 ///
 /// The environment variable `CFG_RELEASE_CHANNEL` is set during the rustc bootstrap
@@ -176,7 +182,7 @@ macro_rules! create_config {
                 ConfigWasSet(self)
             }
 
-            fn fill_from_parsed_config(mut self, parsed: PartialConfig) -> Config {
+            fn fill_from_parsed_config(mut self, parsed: PartialConfig, dir: &Path) -> Config {
             $(
                 if let Some(val) = parsed.$i {
                     if self.$i.3 {
@@ -195,6 +201,7 @@ macro_rules! create_config {
             )+
                 self.set_heuristics();
                 self.set_license_template();
+                self.set_ignore(dir);
                 self
             }
 
@@ -216,7 +223,7 @@ macro_rules! create_config {
                 }
             }
 
-            pub fn from_toml(toml: &str) -> Result<Config, String> {
+            pub fn from_toml(toml: &str, dir: &Path) -> Result<Config, String> {
                 let parsed: ::toml::Value =
                     toml.parse().map_err(|e| format!("Could not parse TOML: {}", e))?;
                 let mut err: String = String::new();
@@ -236,7 +243,7 @@ macro_rules! create_config {
                         if !err.is_empty() {
                             eprint!("{}", err);
                         }
-                        Ok(Config::default().fill_from_parsed_config(parsed_config))
+                        Ok(Config::default().fill_from_parsed_config(parsed_config, dir: &Path))
                     }
                     Err(e) => {
                         err.push_str("Error: Decoding config file failed:\n");
@@ -300,7 +307,8 @@ macro_rules! create_config {
                 let mut file = File::open(&file_path)?;
                 let mut toml = String::new();
                 file.read_to_string(&mut toml)?;
-                Config::from_toml(&toml).map_err(|err| Error::new(ErrorKind::InvalidData, err))
+                Config::from_toml(&toml, file_path.parent().unwrap())
+                    .map_err(|err| Error::new(ErrorKind::InvalidData, err))
             }
 
             /// Resolve the config for input in `dir`.
@@ -401,6 +409,10 @@ macro_rules! create_config {
                     }
                 }
             }
+
+            fn set_ignore(&mut self, dir: &Path) {
+                self.ignore.2.add_prefix(dir);
+            }
         }
 
         // Template for the default configuration
diff --git a/src/config/mod.rs b/src/config/mod.rs
index 0d4ec8557d3..301b9e06b01 100644
--- a/src/config/mod.rs
+++ b/src/config/mod.rs
@@ -141,6 +141,8 @@ create_config! {
         "Report all, none or unnumbered occurrences of TODO in source file comments";
     report_fixme: ReportTactic, ReportTactic::Never, false,
         "Report all, none or unnumbered occurrences of FIXME in source file comments";
+    ignore: IgnoreList, IgnoreList::default(), false,
+        "Skip formatting the specified files and directories.";
 
     // Not user-facing.
     verbose: bool, false, false, "Use verbose output";
@@ -208,7 +210,8 @@ mod test {
 
     #[test]
     fn test_was_set() {
-        let config = Config::from_toml("hard_tabs = true").unwrap();
+        use std::path::Path;
+        let config = Config::from_toml("hard_tabs = true", Path::new("")).unwrap();
 
         assert_eq!(config.was_set().hard_tabs(), true);
         assert_eq!(config.was_set().verbose(), false);
diff --git a/src/config/options.rs b/src/config/options.rs
index dcea4706ace..7a5f9785b9b 100644
--- a/src/config/options.rs
+++ b/src/config/options.rs
@@ -8,9 +8,14 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use syntax::codemap::FileName;
+
 use config::config_type::ConfigType;
 use config::lists::*;
 
+use std::collections::HashSet;
+use std::path::{Path, PathBuf};
+
 /// Macro for deriving implementations of Serialize/Deserialize for enums
 #[macro_export]
 macro_rules! impl_enum_serialize_and_deserialize {
@@ -244,3 +249,68 @@ impl ::std::str::FromStr for WidthHeuristics {
         Err("WidthHeuristics is not parsable")
     }
 }
+
+/// A set of directories, files and modules that rustfmt should ignore.
+#[derive(Default, Deserialize, Serialize, Clone, Debug)]
+pub struct IgnoreList {
+    directories: Option<HashSet<PathBuf>>,
+    files: Option<HashSet<PathBuf>>,
+}
+
+impl IgnoreList {
+    fn add_prefix_inner(set: &HashSet<PathBuf>, dir: &Path) -> HashSet<PathBuf> {
+        set.iter()
+            .map(|s| {
+                if s.has_root() {
+                    s.clone()
+                } else {
+                    let mut path = PathBuf::from(dir);
+                    path.push(s);
+                    path
+                }
+            })
+            .collect()
+    }
+
+    pub fn add_prefix(&mut self, dir: &Path) {
+        macro add_prefix_inner_with ($($field: ident),* $(,)*) {
+            $(if let Some(set) = self.$field.as_mut() {
+                *set = IgnoreList::add_prefix_inner(set, dir);
+            })*
+        }
+
+        add_prefix_inner_with!(directories, files);
+    }
+
+    fn is_ignore_file(&self, path: &Path) -> bool {
+        self.files.as_ref().map_or(false, |set| set.contains(path))
+    }
+
+    fn is_under_ignore_dir(&self, path: &Path) -> bool {
+        if let Some(ref dirs) = self.directories {
+            for dir in dirs {
+                if path.starts_with(dir) {
+                    return true;
+                }
+            }
+        }
+
+        false
+    }
+
+    pub fn skip_file(&self, file: &FileName) -> bool {
+        if let FileName::Real(ref path) = file {
+            self.is_ignore_file(path) || self.is_under_ignore_dir(path)
+        } else {
+            false
+        }
+    }
+}
+
+impl ::std::str::FromStr for IgnoreList {
+    type Err = &'static str;
+
+    fn from_str(_: &str) -> Result<Self, Self::Err> {
+        Err("IgnoreList is not parsable")
+    }
+}
diff --git a/src/lib.rs b/src/lib.rs
index 9447155ee92..ebd94e1b3d4 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -338,7 +338,7 @@ where
     // nothing to distinguish the nested module contents.
     let skip_children = config.skip_children() || config.write_mode() == config::WriteMode::Plain;
     for (path, module) in modules::list_files(krate, parse_session.codemap())? {
-        if skip_children && path != *main_file {
+        if (skip_children && path != *main_file) || config.ignore().skip_file(&path) {
             continue;
         }
         should_emit_verbose(&path, config, || println!("Formatting {}", path));
diff --git a/tests/lib.rs b/tests/lib.rs
index 9abe08ba9e0..9309941983d 100644
--- a/tests/lib.rs
+++ b/tests/lib.rs
@@ -293,7 +293,7 @@ fn format_lines_errors_are_reported() {
 fn format_lines_errors_are_reported_with_tabs() {
     let long_identifier = String::from_utf8(vec![b'a'; 97]).unwrap();
     let input = Input::Text(format!("fn a() {{\n\t{}\n}}", long_identifier));
-    let config = Config::from_toml("hard_tabs = true").unwrap();
+    let config = Config::from_toml("hard_tabs = true", Path::new("")).unwrap();
     let (error_summary, _file_map, _report) =
         format_input::<io::Stdout>(input, &config, None).unwrap();
     assert!(error_summary.has_formatting_errors());
@@ -433,7 +433,7 @@ fn get_config(config_file: Option<&Path>) -> Config {
         .read_to_string(&mut def_config)
         .expect("Couldn't read config");
 
-    Config::from_toml(&def_config).expect("Invalid toml")
+    Config::from_toml(&def_config, Path::new("tests/config/")).expect("Invalid toml")
 }
 
 // Reads significant comments of the form: // rustfmt-key: value