根据文件名复制文件到目录

car*_*ock 5 command-line bash filemanager rename

我有一个包含数千个文件的 webdav 服务器:

\n
\xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 Sync\n     \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 20180719_120823.jpg\n     \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 20180719_120933.jpg\n     \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 20190719_120955.jpg\n     \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 20190719_121023.jpg\n     \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 20190719_121032.jpg\n     \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 20190720_121037.jpg\n     \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 20190721_120823.mp4\n     \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 20190822_220013.jpg\n     \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 20190822_230155.mp4\n                 "\n                 "\n
Run Code Online (Sandbox Code Playgroud)\n

文件名的第一部分是 YYYYMMDD。我想用它来使用以下结构将文件复制到另一个驱动器。如果将 MM 翻译为月份名称,则有奖励...:

\n
\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 2018\n\xe2\x94\x82    \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 Jul\n\xe2\x94\x82         \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 20180719_120823.jpg\n\xe2\x94\x82         \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 20180719_120933.jpg\n\xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 2019 \n     \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 Jul\n     \xe2\x94\x82    \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 20190719_120955.jpg\n     \xe2\x94\x82    \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 20190719_121023.jpg\n     \xe2\x94\x82    \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 20190719_121032.jpg\n     \xe2\x94\x82    \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 20190720_121037.jpg\n     \xe2\x94\x82    \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 20190721_120823.mp4\n     \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 Aug\n          \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 20190822_220013.jpg\n          \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 20190822_230155.mp4\n
Run Code Online (Sandbox Code Playgroud)\n

我可以手动创建年/月结构。\n但是,如果目录不存在,则创建目录会很好。\n脚本将每天运行一次,如果文件已经存在,我们会跳过它。

\n

Raf*_*ffa 10

可以在 Bash 中完成类似的操作:

\n

您所在的地方:

\n
$ tree Sync/\nSync/\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 20180719_120823.jpg\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 20190719_120823.jpg\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 20190719_120920.jpg\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 20190720_121037.jpg\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 20190822_120823.jpg\n\xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 20190822_120823.mp4\n\n1 directory, 6 files\n
Run Code Online (Sandbox Code Playgroud)\n

然后,你这样做:

\n
$ tree Sync/\nSync/\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 20180719_120823.jpg\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 20190719_120823.jpg\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 20190719_120920.jpg\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 20190720_121037.jpg\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 20190822_120823.jpg\n\xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 20190822_120823.mp4\n\n1 directory, 6 files\n
Run Code Online (Sandbox Code Playgroud)\n

要得到:

\n
$ tree Dest/\nDest/\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 2018\n\xe2\x94\x82\xc2\xa0\xc2\xa0 \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 Jul\n\xe2\x94\x82\xc2\xa0\xc2\xa0     \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 20180719_120823.jpg\n\xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 2019\n    \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 Aug\n    \xe2\x94\x82\xc2\xa0\xc2\xa0 \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 20190822_120823.jpg\n    \xe2\x94\x82\xc2\xa0\xc2\xa0 \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 20190822_120823.mp4\n    \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 Jul\n        \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 20190719_120823.jpg\n        \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 20190719_120920.jpg\n        \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 20190720_121037.jpg\n\n6 directories, 6 files\n
Run Code Online (Sandbox Code Playgroud)\n
\n

请注意date上面用于将月份数字翻译为月份名称的命令将根据系统上的默认区域设置(即语言)进行操作,但您可以将其更改为另一种语言/区域设置(需要已安装在您的系统上):临时LC_ALL在同一行和命令之前设置环境变量date,例如将月份数字转换为瑞典语月份名称,您可以将上述相关行从:

\n
$ for f in Sync/*\n  do\n  if [ -f "$f" ]\n    then\n    n="${f/*\\//}" # Get filename\n    y="${n:0:4}" # Get Year part\n    m="${n:4:2}" # Get Month part\n    mn="$(date -d "$m/01/2000" "+%b")" # Translate Month number to name\n    mkdir -p Dest/"${y}/${mn}" # Create destination directories if they don\'t exist\n    cp -nv -- "$f" Dest/"${y}/${mn}/"\n    fi\n  done\n\'Sync/20180719_120823.jpg\' -> \'Dest/2018/Jul/20180719_120823.jpg\'\n\'Sync/20190719_120823.jpg\' -> \'Dest/2019/Jul/20190719_120823.jpg\'\n\'Sync/20190719_120920.jpg\' -> \'Dest/2019/Jul/20190719_120920.jpg\'\n\'Sync/20190720_121037.jpg\' -> \'Dest/2019/Jul/20190720_121037.jpg\'\n\'Sync/20190822_120823.jpg\' -> \'Dest/2019/Aug/20190822_120823.jpg\'\n\'Sync/20190822_120823.mp4\' -> \'Dest/2019/Aug/20190822_120823.mp4\'\n
Run Code Online (Sandbox Code Playgroud)\n

到:

\n
mn="$(LC_ALL=sv_SE.utf8 date -d "$m/01/2000" "+%b")" # Translate Month number to Swedish name\n
Run Code Online (Sandbox Code Playgroud)\n

.. 例如,它将月份数字翻译10为瑞典语简称okt。如果您想要全名,您可以更改"+%b""+%B",将分别翻译为oktober

\n


ter*_*don 10

这是一种方法:

declare -A months=( 
 [01]="Jan" 
 [02]="Feb" 
 [03]="Mar" 
 [04]="Apr" 
 [05]="May" 
 [06]="Jun" 
 [07]="Jul" 
 [08]="Aug" 
 [09]="Sep" 
 [10]="Oct" 
 [11]="Nov" 
 [12]="Dec"
) 

for file in Sync/*; do
    year=$(cut -c 1-4 <<<"${file##*/}") 
    month=$(cut -c 5-6 <<<"${file##*/}")
    mkdir -p "$year/${months[$month]}"
    cp -n -- "$file" "$year/${months[$month]}"
 done

Run Code Online (Sandbox Code Playgroud)

首先,我们创建一个将数字链接到月份名称的关联数组。然后,对于Sync目录中的每个文件,我们用来cut提取年份和月份(有关格式的说明,请参阅https://tldp.org/LDP/abs/html/string-manipulation.html${file##*/})。然后,mkdir -p如果目录不存在,则创建该目录,然后移动文件。-n确保现有文件不被覆盖的选项(cp感谢添加它的@Raffa!)。


car*_*ock 6

感谢您的意见...这很有趣!
我最终结合了上述两个建议。

#! /bin/bash

# Declare monts in Swedish
declare -A months=(
 [01]="Januari"
 [02]="Februari"
 [03]="Mars"
 [04]="April"
 [05]="Maj"
 [06]="Juni"
 [07]="Juli"
 [08]="Augusti"
 [09]="September"
 [10]="Oktober"
 [11]="November"
 [12]="December"
)

for f in /mnt/4TB/apa/*
do
  if [ -f "$f" ]; then
   filename="${f##*/}" # Get the base filename

    # pick the first 9 characters
    first_nine="${filename:0:9}"

    # Use regular expression to check if the first nine characters are 8 digits followed by an underscore
    if [[ "$first_nine" =~ ^[0-9]{8}_ ]]; then
           n="${f/*\//}" # Get filename
           y="${n:0:4}" # Get Year part
           m="${n:4:2}" # Get Month part
           mn="${months[$m]}" # Get Month in Swedish
           mkdir -p /mnt/4TB/bepa/"${y}/${mn}" # Create destination directories if they don't exist
           cp -np -- "$f" /mnt/4TB/bepa/"${y}/${mn}/" # Copy file
    fi
  fi
done
Run Code Online (Sandbox Code Playgroud)

  • 我认为@Raffa点(1)已被揭穿 - 例如参见[#之间是否允许空格!和 shebang 中的 /bin/bash?](https://unix.stackexchange.com/questions/276751/is-space-allowed- Between-and-bin-bash-in-shebang) (2认同)