ls和mv问题。可以列出文件但是在尝试移动系统时说没有这样的文件

问题描述 投票:0回答:2

可以使用 ls 列出文件,但是当尝试使用 mv 移动时,系统说没有这样的文件。 我输入了

 ~$ sudo mv "$(ls -lt /media/cache | grep ^- | head -1 | awk '{ print $9 }')" /media/cache/2

我有

mv: cannot stat 'ea9a1f08ddcf32c6e3cfea3b055d45e1e3690ca75c7bedf1ce938a2fc8bf507e.tmp': 没有那个文件或目录

这只能意味着 ls 可以列出这个 ea9a1f08ddcf32c6e3cfea3b055d45e1e3690ca75c7bedf1ce938a2fc8bf507e.tmp 文件,但 mv 不能移动它。我哪里出错了?

awk grep ls mv
2个回答
0
投票

您的解决方案不起作用,因为

ls
管道输出文件名,而不是整个文件路径,因此
mv
尝试在当前目录(而不是
/media/cache
)中查找该文件并失败。查看管道,您正在尝试从
/media/cache
目录中选择第一个文件,并将其移动到
/media/cache/2
。这可以使用带中断的 for 循环来实现:

for f in /media/cache/*; do [ -f "$f" ] && { mv "$f" /media/cache/2; break; }; done

0
投票

在命令管道中使用文件名很难可靠地完成,因为文件名中几乎可以包含任何字符,包括换行符。正如评论中提到的,尝试使用

ls
的输出也不是一个好主意。

我可以一次移动 2-3 个文件吗?

处理多个文件的一些方法(或者只有 1 个,但希望有一些小的明显调整):

使用

zsh
,您可以利用它的 glob 限定符 来控制从通配符扩展返回哪些文件,而不仅仅是基于名称的方式:

files=( /media/cache/*(.) )
mv "${(@)files[1,3]}" /media/cache/2

限定符

(.)
仅匹配保存在数组中的常规文件。然后将它的前三个元素用作
mv
.

的参数

在其他 shell 中,使用循环通常是更好的选择(类似于 Discussian 的回答中的循环,但在 3 个文件后中断,而不是 1 个):

nfiles=0
for file in /media/cache/*; do
  if [ -f "$file" ]; then
    mv "$file" /media/cache/2/
    nfiles=$((nfiles + 1))
    if [ $nfiles -eq 3 ]; then
      break
    fi
  fi
done

或者只是用一种更强大的语言将工作放到一行中,例如

perl

perl -MFile::Copy -MList::Util=head -e 'move($_, "/media/cache/2/") for head(3, grep(-f, </media/cache/*>))'

tcl

tclsh <<'EOF'
set files [lsort [glob -nocomplain -type f {/media/cache/*}]]
if {[llength $files]} {
  file rename -- {*}[lrange $files 0 2] /media/cache/2/
}
EOF
© www.soinside.com 2019 - 2024. All rights reserved.