ya env output
Yazi
Version : 26.5.6 (Homebrew 2026-05-05)
Debug : false
Triple : aarch64-apple-darwin (macos-aarch64)
Rustc : 1.95.0 (59807616 2026-04-14)
Backtrace: None
Ya
Version: 26.5.6 (Homebrew 2026-05-05)
Emulator
TERM : Some("xterm-kitty")
TERM_PROGRAM : None
TERM_PROGRAM_VERSION: None
Brand.from_env : Some(Kitty)
Emulator.detect : Emulator { kind: Left(Kitty), version: "kitty(0.46.2)", light: false, csi_16t: (15, 31), force_16t: false }
Adapter
Adapter.matches : Kgp
Dimension.available: Dimension { rows: 50, columns: 193, width: 2895, height: 1550 }
Desktop
XDG_SESSION_TYPE : None
WAYLAND_DISPLAY : None
DISPLAY : None
SWAYSOCK : None
HYPRLAND_INSTANCE_SIGNATURE: None
WAYFIRE_SOCKET : None
SSH
shared.in_ssh_connection: false
WSL
WSL: false
Variables
SHELL : Some("/bin/zsh")
EDITOR : Some("nvim")
VISUAL : Some("nvim")
YAZI_FILE_ONE : None
YAZI_CONFIG_HOME : None
YAZI_ZOXIDE_OPTS : None
SSH_AUTH_SOCK : Some("/private/tmp/com.apple.launchd.MyJnc2iptR/Listeners")
FZF_DEFAULT_OPTS : Some("--bind=tab:up,shift-tab:down --style=default --preview=\"[[ -f {} ]] && bat --color=always --style=numbers --line-range=:500 {} || [[ -d {} ]] && eza -1 --color=always {} || [[ {} == http* ]] && curl -sL --max-time 3 {} | w3m -dump -T text/html | head -80 || echo {}\"")
FZF_DEFAULT_COMMAND: Some("fd")
Text Opener
default : Some(OpenerRule { id: Id(24), run: NonEmptyString("${EDITOR:-nvim} %s"), block: true, orphan: false, desc: "$EDITOR", for: Unix, spread: true })
block-create: Some(OpenerRule { id: Id(24), run: NonEmptyString("${EDITOR:-nvim} %s"), block: true, orphan: false, desc: "$EDITOR", for: Unix, spread: true })
block-rename: Some(OpenerRule { id: Id(24), run: NonEmptyString("${EDITOR:-nvim} %s"), block: true, orphan: false, desc: "$EDITOR", for: Unix, spread: true })
Multiplexers
TMUX : false
tmux version : tmux 3.6b
tmux build flags : enable-sixel=Supported
ZELLIJ_SESSION_NAME: None
Zellij version : No such file or directory (os error 2)
Dependencies
file : 5.41
ueberzugpp : No such file or directory (os error 2)
ffmpeg/ffprobe: 8.1.1 / 8.1.1
pdftoppm : No such file or directory (os error 2)
magick : 7.1.2-24
fzf : 0.73.1
fd/fdfind : 10.4.2 / No such file or directory (os error 2)
rg : 15.1.0
chafa : No such file or directory (os error 2)
zoxide : 0.9.9
7zz/7z : 26.01 / No such file or directory (os error 2)
resvg : No such file or directory (os error 2)
jq : 1.7.1
Clipboard
wl-copy/paste: No such file or directory (os error 2) / No such file or directory (os error 2)
xclip : No such file or directory (os error 2)
xsel : No such file or directory (os error 2)
Routine
`file -bL --mime-type`: text/plain
See https://yazi-rs.github.io/docs/plugins/overview#debugging on how to enable logging or debug runtime errors.
Please describe the problem you're trying to solve
Currently, bulk rename fails when the rename operations contain a cycle. For example, I want to rename:
file1 → file2
file2 → file3
file3 → file1
The goal is to support cyclic renames during bulk rename.
Would you be willing to contribute this feature?
Describe the solution you'd like
My idea is to modify this function so that it returns both normal rename chains and cycle rename groups:
|
fn prioritized_paths(old: Vec<Tuple>, new: Vec<Tuple>) -> Vec<(Tuple, Tuple)> { |
|
let orders: HashMap<_, _> = old.iter().enumerate().map(|(i, t)| (t, i)).collect(); |
|
let mut incomes: HashMap<_, _> = old.iter().map(|t| (t, false)).collect(); |
|
let mut todos: HashMap<_, _> = old |
|
.iter() |
|
.zip(new) |
|
.map(|(o, n)| { |
|
incomes.get_mut(&n).map(|b| *b = true); |
|
(o, n) |
|
}) |
|
.collect(); |
Normal chains can be processed as they are. For cycle groups, add a temporary rename to break the cycle. For example, the rename order will be:
file1 → .tmp
file3 → file1
file2 → file3
.tmp → file2
This function can be used to produce the cycle groups, and it reuses the todos and orders in prioritized_paths.
fn partition_cycles(
mut todos: HashMap<&Tuple, Tuple>,
orders: &HashMap<&Tuple, usize>,
) -> Vec<Renames> {
let mut starts = todos.keys().copied().collect();
starts.sort_unstable_by(|a, b| orders[a].cmp(&orders[b]));
let mut cycles = Vec::new();
for start in starts {
if !todos.contains_key(start) {
continue;
}
let mut cycle = Vec::new();
let mut cur = start;
while let Some(next) = todos.remove(cur) {
cycle.push((cur.clone(), next.clone()));
let Some((&owner, _)) = todos.get_key_value(&next) else { break };
cur = owner;
}
cycles.push(cycle);
}
cycles
}
Additional context
I saw this issue but it was closed #3718.
Checklist
ya envoutputYazi Version : 26.5.6 (Homebrew 2026-05-05) Debug : false Triple : aarch64-apple-darwin (macos-aarch64) Rustc : 1.95.0 (59807616 2026-04-14) Backtrace: None Ya Version: 26.5.6 (Homebrew 2026-05-05) Emulator TERM : Some("xterm-kitty") TERM_PROGRAM : None TERM_PROGRAM_VERSION: None Brand.from_env : Some(Kitty) Emulator.detect : Emulator { kind: Left(Kitty), version: "kitty(0.46.2)", light: false, csi_16t: (15, 31), force_16t: false } Adapter Adapter.matches : Kgp Dimension.available: Dimension { rows: 50, columns: 193, width: 2895, height: 1550 } Desktop XDG_SESSION_TYPE : None WAYLAND_DISPLAY : None DISPLAY : None SWAYSOCK : None HYPRLAND_INSTANCE_SIGNATURE: None WAYFIRE_SOCKET : None SSH shared.in_ssh_connection: false WSL WSL: false Variables SHELL : Some("/bin/zsh") EDITOR : Some("nvim") VISUAL : Some("nvim") YAZI_FILE_ONE : None YAZI_CONFIG_HOME : None YAZI_ZOXIDE_OPTS : None SSH_AUTH_SOCK : Some("/private/tmp/com.apple.launchd.MyJnc2iptR/Listeners") FZF_DEFAULT_OPTS : Some("--bind=tab:up,shift-tab:down --style=default --preview=\"[[ -f {} ]] && bat --color=always --style=numbers --line-range=:500 {} || [[ -d {} ]] && eza -1 --color=always {} || [[ {} == http* ]] && curl -sL --max-time 3 {} | w3m -dump -T text/html | head -80 || echo {}\"") FZF_DEFAULT_COMMAND: Some("fd") Text Opener default : Some(OpenerRule { id: Id(24), run: NonEmptyString("${EDITOR:-nvim} %s"), block: true, orphan: false, desc: "$EDITOR", for: Unix, spread: true }) block-create: Some(OpenerRule { id: Id(24), run: NonEmptyString("${EDITOR:-nvim} %s"), block: true, orphan: false, desc: "$EDITOR", for: Unix, spread: true }) block-rename: Some(OpenerRule { id: Id(24), run: NonEmptyString("${EDITOR:-nvim} %s"), block: true, orphan: false, desc: "$EDITOR", for: Unix, spread: true }) Multiplexers TMUX : false tmux version : tmux 3.6b tmux build flags : enable-sixel=Supported ZELLIJ_SESSION_NAME: None Zellij version : No such file or directory (os error 2) Dependencies file : 5.41 ueberzugpp : No such file or directory (os error 2) ffmpeg/ffprobe: 8.1.1 / 8.1.1 pdftoppm : No such file or directory (os error 2) magick : 7.1.2-24 fzf : 0.73.1 fd/fdfind : 10.4.2 / No such file or directory (os error 2) rg : 15.1.0 chafa : No such file or directory (os error 2) zoxide : 0.9.9 7zz/7z : 26.01 / No such file or directory (os error 2) resvg : No such file or directory (os error 2) jq : 1.7.1 Clipboard wl-copy/paste: No such file or directory (os error 2) / No such file or directory (os error 2) xclip : No such file or directory (os error 2) xsel : No such file or directory (os error 2) Routine `file -bL --mime-type`: text/plain See https://yazi-rs.github.io/docs/plugins/overview#debugging on how to enable logging or debug runtime errors.Please describe the problem you're trying to solve
Currently, bulk rename fails when the rename operations contain a cycle. For example, I want to rename:
file1→file2file2→file3file3→file1The goal is to support cyclic renames during bulk rename.
Would you be willing to contribute this feature?
Describe the solution you'd like
My idea is to modify this function so that it returns both normal rename chains and cycle rename groups:
yazi/yazi-actor/src/mgr/bulk_rename.rs
Lines 200 to 210 in 07a5deb
Normal chains can be processed as they are. For cycle groups, add a temporary rename to break the cycle. For example, the rename order will be:
file1→.tmpfile3→file1file2→file3.tmp→file2This function can be used to produce the cycle groups, and it reuses the
todosandordersinprioritized_paths.Additional context
I saw this issue but it was closed #3718.
Checklist