如何移动子文件夹中除某些文件外的所有文件

How to move all files in a subfolder except certain files

我一般都是用filezilla下载到我nas的/Public/Downloads目录下

我制作了一个在下载队列完成时由 filezilla 执行的脚本,所以我所有的下载都移到了 /Public/Downloads/Completed。我的目录 /Public/Downloads 也包含两个文件和三个目录,不能移动。

folder.jpg
log.txt
Temp
Cache
Completed

我试过这个命令:

find /Public/Downloads/* -maxdepth 1 | grep -v Completed | grep -v Cache | grep -v Temp | grep -v log.txt | grep -v folder.jpg | xargs -i mv {} /Public/Downloads/Completed

这适用于没有特殊字符命名的下载文件和文件夹:它们被移动到 /Public/Downloads/Completed 但是当有 à 或其他特殊内容时,xarg 会抱怨 unmatched single quote;默认情况下引号对 xargs 是特殊的,除非你使用 -0 选项

我自己搜索了一个解决方案,但没有找到满足我需要的结合文件和目录的查找、grep 和 xargs 的解决方案。

我必须如何修改我的命令?

所以我改变了使用临时文本文件循环的策略:

#!/bin/bash

ls -p /Public/Downloads | grep -v "Cache/" | grep -v "Temp/" | grep -v "Completed/" | grep -v 'log.txt' | grep -v 'folder.jpg' >/Public/Downloads/Completed/temp.txt
cat /Public/Downloads/Completed/temp.txt |\
    while IFS='' read -r CURRENT || [ -n "$CURRENT" ]; do
    mv /Public/Downloads/"$CURRENT" /Public/Downloads/Completed
    done
rm /Public/Downloads/Completed/temp.txt

1) 我在 "temp.txt"

中用 "ls" 写了一个要移动的目录和文件列表

2) "temp.txt" 的每一行都传递到 $CURRENT 变量中。所以每个文件和目录都用 "mv" 一个一个地移动。如果目录或文件名称中的 "space" 字符

,变量 $CURRENT 在 mv 命令中被双引号

3) "temp.txt" 被删除

这只是对您的更改策略的建议,与xargs无关。对于外部工具,您只需要 bash shell 和 mv

#!/usr/bin/env bash

shopt -s nullglob extglob

array=( 
  folder.jpg
  log.txt
  Temp
  Cache 
  Completed
)

to_skip=$(IFS='|'; printf '%s' "*@(${array[*]})")

for item in /Public/Downloads/*; do
  [[ $item == $to_skip ]] && continue
  echo mv -v "$item" /Public/Downloads/Completed/ || exit
done
  • 如果您认为输出正确,请删除 echo
  • 添加 -x 例如set -x(在 shebang 之后)选项以查看代码正在执行的 which/what 或 bash -x my_script,假设 my_script 是您的脚本的名称。

根据 OP 输入,主要问题是文件名带有“特殊”字符,包括 space。两个选项:

  • 如果 none 个输入文件在文件名中嵌入了换行符(这种情况),可以通过将分隔字符串显式指定为换行符 (-d '\ n').见下文
  • 如果任何文件的名称中可以包含新行,则整个管道必须使用以零结尾的字符串。这里好像不是这样。
find /Public/Downloads/* -maxdepth 1 |
    grep -v Completed |
    grep -v Cache |
    grep -v Temp |
    grep -v log.txt |
    grep -v folder.jpg |
    xargs -d '\n' -i mv {} /Public/Downloads/Completed