Browse Source

First, relatively simple implementation.

tags/0.1.0^0
Bauke 7 months ago
parent
commit
63911fd15d
Signed by: Bauke <me@bauke.xyz> GPG Key ID: C1C0F29952BCF558
4 changed files with 409 additions and 2 deletions
  1. +234
    -0
      Cargo.lock
  2. +4
    -1
      Cargo.toml
  3. +29
    -0
      README.md
  4. +142
    -1
      source/main.rs

+ 234
- 0
Cargo.lock View File

@@ -1,6 +1,240 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
[[package]]
name = "ansi_term"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
]

[[package]]
name = "atty"
version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"hermit-abi 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.74 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
]

[[package]]
name = "bitflags"
version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"

[[package]]
name = "clap"
version = "2.33.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
"atty 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
"bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
"textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
"unicode-width 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
"vec_map 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)",
]

[[package]]
name = "execute"
version = "0.2.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"execute-command-macro 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
"execute-command-tokens 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
"generic-array 0.14.3 (registry+https://github.com/rust-lang/crates.io-index)",
]

[[package]]
name = "execute-command-macro"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"execute-command-macro-impl 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
]

[[package]]
name = "execute-command-macro-impl"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"execute-command-tokens 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 1.0.36 (registry+https://github.com/rust-lang/crates.io-index)",
]

[[package]]
name = "execute-command-tokens"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"

[[package]]
name = "generic-array"
version = "0.14.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"typenum 1.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
"version_check 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)",
]

[[package]]
name = "hermit-abi"
version = "0.1.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.74 (registry+https://github.com/rust-lang/crates.io-index)",
]

[[package]]
name = "libc"
version = "0.2.74"
source = "registry+https://github.com/rust-lang/crates.io-index"

[[package]]
name = "proc-macro2"
version = "1.0.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"unicode-xid 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
]

[[package]]
name = "quote"
version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"proc-macro2 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)",
]

[[package]]
name = "recursive-execute"
version = "0.1.0"
dependencies = [
"clap 2.33.1 (registry+https://github.com/rust-lang/crates.io-index)",
"execute 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
"walkdir 2.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
]

[[package]]
name = "same-file"
version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"winapi-util 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
]

[[package]]
name = "strsim"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"

[[package]]
name = "syn"
version = "1.0.36"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"proc-macro2 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
"unicode-xid 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
]

[[package]]
name = "textwrap"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"unicode-width 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
]

[[package]]
name = "typenum"
version = "1.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"

[[package]]
name = "unicode-width"
version = "0.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index"

[[package]]
name = "unicode-xid"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"

[[package]]
name = "vec_map"
version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"

[[package]]
name = "version_check"
version = "0.9.2"
source = "registry+https://github.com/rust-lang/crates.io-index"

[[package]]
name = "walkdir"
version = "2.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"same-file 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi-util 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
]

[[package]]
name = "winapi"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
]

[[package]]
name = "winapi-i686-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"

[[package]]
name = "winapi-util"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
]

[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"

[metadata]
"checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b"
"checksum atty 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
"checksum bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
"checksum clap 2.33.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bdfa80d47f954d53a35a64987ca1422f495b8d6483c0fe9f7117b36c2a792129"
"checksum execute 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "f3edb78b01d2e376cce298c57f5d569e16705f4737c7afcd7f5da30079f4a1e3"
"checksum execute-command-macro 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ab1325ccd13c04c9ef1bb5d51b5dec468699981831f78df28ca970cf23f3c143"
"checksum execute-command-macro-impl 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "530d15a1a0052eee4f4a78916f4e89fb2fccc96d3967134b699ccdd97bec496f"
"checksum execute-command-tokens 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "39b5a8386d3f481bd7c5dbc487c0d8d4ada0fd680625fd32147a87e123ebdf13"
"checksum generic-array 0.14.3 (registry+https://github.com/rust-lang/crates.io-index)" = "60fb4bb6bba52f78a471264d9a3b7d026cc0af47b22cd2cffbc0b787ca003e63"
"checksum hermit-abi 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)" = "3deed196b6e7f9e44a2ae8d94225d80302d81208b1bb673fd21fe634645c85a9"
"checksum libc 0.2.74 (registry+https://github.com/rust-lang/crates.io-index)" = "a2f02823cf78b754822df5f7f268fb59822e7296276d3e069d8e8cb26a14bd10"
"checksum proc-macro2 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)" = "04f5f085b5d71e2188cb8271e5da0161ad52c3f227a661a3c135fdf28e258b12"
"checksum quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "aa563d17ecb180e500da1cfd2b028310ac758de548efdd203e18f283af693f37"
"checksum same-file 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502"
"checksum strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
"checksum syn 1.0.36 (registry+https://github.com/rust-lang/crates.io-index)" = "4cdb98bcb1f9d81d07b536179c269ea15999b5d14ea958196413869445bb5250"
"checksum textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
"checksum typenum 1.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "373c8a200f9e67a0c95e62a4f52fbf80c23b4381c05a17845531982fa99e6b33"
"checksum unicode-width 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "9337591893a19b88d8d87f2cec1e73fad5cdfd10e5a6f349f498ad6ea2ffb1e3"
"checksum unicode-xid 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564"
"checksum vec_map 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191"
"checksum version_check 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b5a972e5669d67ba988ce3dc826706fb0a8b01471c088cb0b6110b805cc36aed"
"checksum walkdir 2.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "777182bc735b6424e1a57516d35ed72cb8019d85c8c9bf536dccb3445c1a2f7d"
"checksum winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
"checksum winapi-util 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"

+ 4
- 1
Cargo.toml View File

@@ -5,7 +5,7 @@ name = "recursive-execute"
description = "Execute a command in specified directories recursively."
version = "0.1.0"
authors = ["Bauke <me@bauke.xyz>"]
license = "MIT/Apache-2.0"
license = "MIT OR Apache-2.0"
repository = "https://git.holllo.cc/Bauke/recursive-execute"
edition = "2018"

@@ -14,3 +14,6 @@ name = "recursive-execute"
path = "source/main.rs"

[dependencies]
clap = "2.33.1"
execute = "0.2.8"
walkdir = "2.3.1"

+ 29
- 0
README.md View File

@@ -26,6 +26,35 @@ chmod +x ./recursive-execute
./recursive-execute --help
```

<details>
<summary>Example output using <code>pwd</code>.</summary>

```sh
$ ./recursive-execute -d="source/" -d="target/" -c="pwd" --depth="1" --verbose
```

Outputs:

```
Executing "pwd" in "source/" (current depth 0), output:
/home/bauke/code/recursive-execute/source

Executing "pwd" in "target/" (current depth 0), output:
/home/bauke/code/recursive-execute/target

Executing "pwd" in "target/debug" (current depth 1), output:
/home/bauke/code/recursive-execute/target/debug

Executing "pwd" in "target/release" (current depth 1), output:
/home/bauke/code/recursive-execute/target/release

Executing "pwd" in "target/rls" (current depth 1), output:
/home/bauke/code/recursive-execute/target/rls

✓ Done!
```
</details>

## License

Open-sourced with either the


+ 142
- 1
source/main.rs View File

@@ -1,3 +1,144 @@
// Standard library modules.
use std::process::Stdio;

// Third-party modules.
use clap::{
crate_authors, crate_description, crate_name, crate_version, App, Arg,
};
use execute::command;
use walkdir::WalkDir;

fn main() {
println!("recursive-execute");
// Define the default CLI values here.
let default_depth = "0";

// Create the CLI with all possible flags and options.
let cli = App::new(crate_name!())
.about(crate_description!())
.author(crate_authors!())
.version(crate_version!())
.args(&[
// Boolean flags.
Arg::with_name("verbose")
.long("verbose")
.long_help("Print extra information while running.")
.takes_value(false),
// Options that are only allowed once.
Arg::with_name("command")
.long("command")
.long_help("The command to execute in each directory.")
.short("c")
.required(true)
.takes_value(true),
Arg::with_name("depth")
.default_value(default_depth)
.long("depth")
.long_help(
"How many directories deep we should go.\nUse -1 for unlimited depth.",
)
.takes_value(true),
// Options that are allowed multiple times.
Arg::with_name("directory")
.long("dir")
.long_help("One or more directories to execute the command in.")
.multiple(true)
.short("d")
.required(true)
.takes_value(true),
])
.get_matches();

// Extract boolean flags.
let verbose = cli.is_present("verbose");

// Extract the command to execute.
let target_command = cli
.value_of("command")
.expect("Failed to extract the command to execute from the CLI");

// Extract the target directories.
let dirs = cli
.values_of("directory")
.expect("Failed to extract the target directories from the CLI");

// Extract the maximum depth we want to walk.
let depth = cli.value_of("depth").unwrap_or(default_depth);

// If -1 is specified, don't bother parsing to a usize.
let infinite_depth = depth == "-1";
let depth = if infinite_depth {
0_usize
} else {
depth
.parse::<usize>()
.expect("Failed to convert --depth to a usize")
};

for dir_root in dirs {
// Create the walker for the specified directory.
let walker = if infinite_depth {
// If infinite depth was specified, don't call `max_depth()`, by default
// WalkDir has no maximum depth.
WalkDir::new(dir_root)
} else {
WalkDir::new(dir_root).max_depth(depth)
};

'walker_loop: for dir in walker {
// Get the current path and depth.
let dir = dir.unwrap();
let current_depth = dir.depth();

// If the current path isn't a directory, skip it.
let dir_path = dir.path();
if !dir_path.is_dir() {
continue 'walker_loop;
}

// Print what we're doing and where we are.
print!(
"Executing \"{}\" in {:?} (current depth {})",
target_command, dir_path, current_depth
);

// If verbose was specified, we're also going to print the output.
if verbose {
println!(", output:");
} else {
println!();
}

// Don't output the command output to stdout if `--verbose` isn't specified.
let target_stdout = if verbose {
Stdio::inherit()
} else {
Stdio::null()
};

// Spawn the command at the directory with the specified stdout.
// Print an error and continue if one occurs.
let mut child = match command(target_command)
.stdout(target_stdout)
.current_dir(dir_path)
.spawn()
{
Ok(value) => value,
Err(err) => {
println!("Error executing command: {}", err);
println!();
continue 'walker_loop;
}
};

// Wait for the command to finish before continuing.
child.wait().expect("Failed to wait for child process");

// If verbose was specified, print an extra newline to make the output more readable.
if verbose {
println!();
}
}
}

println!("✓ Done!");
}

Loading…
Cancel
Save