同じプレフィックスとサフィックスを持つファイルを同じディレクトリに移動するためのアルゴリズム設計と C コードの実装

同じプレフィックスとサフィックスを持つファイルを同じディレクトリに移動するためのアルゴリズム設計と C コードの実装

1. 要件の説明

Linux システムの複数のディレクトリに、同じプレフィックスとサフィックスを持つファイルがいくつかあります。それらを同じディレクトリに移動するプログラムを作成してください。

たとえば、FileDir1、FileDir2、FileDir3 という 3 つのソース ディレクトリがあり、それぞれに File_1.txt、File_2.txt、File_3.txt というファイルが含まれています。これら 3 つのファイルはプレフィックス (File_) とサフィックス (txt) が同じなので、同じ結果ディレクトリ (GatherDir であると仮定) に移動されます。

2. アルゴリズム設計

要件に基づいて、図 1 に示すプログラム フローを採​​用できます。

図1 全体的なプロセスフロー

3. 特別なプロセスに関する考慮事項

プログラムを作成する過程では、次のような特別なプロセスが考慮されます。

1. ディレクトリのスキャン中にエラーが発生した場合、プログラムは次のディレクトリをスキャンせずに停止します。

2. 空のファイル(つまり、ファイル サイズが 0)がある場合は、結果ディレクトリに移動せずに、ソース ディレクトリで直接削除します。

3. ソース ディレクトリに配置されたファイルをいつでも処理できるように、プログラムはソース ディレクトリを一定の間隔 (1 分など) でスキャンします。つまり、人間による操作がなければ、プログラムは起動後継続的に実行されます。

4. プログラムコード

  1. /******************************************************************************************
  2. * 著作権 (C) 2016、Zhou Zhaoxiong。
  3. *
  4. * ファイル名: FileGather.c
  5. * ファイルID: なし
  6. * コンテンツの概要: さまざまなディレクトリにある同じプレフィックスを持つファイルを 1 つのディレクトリに集めます
  7. * その他の指示: なし
  8. * 現在のバージョン: V1.0
  9. * 著者: 周昭雄
  10. * 完成日: 20160513
  11. *
  12. ******************************************************************************/
  13. #include <stdio.h>
  14. #include <文字列.h>
  15. #include <dirent.h>
  16. #include <ftw.h>
  17. #include <時間.h>
  18.  
  19. // データ型を再定義する
  20. typedef 符号付きint INT32;
  21. typedef 符号なしint UINT32;
  22. typedef unsigned char UINT8;
  23.  
  24. //グローバル変数の定義
  25. UINT8 g_szGatherDir[256] = {0}; // サマリーファイルのディレクトリ
  26. UINT8 g_szFilePrefix[20] = {0}; // 要約するファイルのプレフィックス
  27. UINT8 g_szFileSuffix[20] = {0}; // 要約するファイルのサフィックス
  28.  
  29.  
  30. // マクロ定義
  31. #define DIRNUM 3 // スキャンするディレクトリの数
  32.  
  33. // 関数宣言
  34. INT32 SelectFlies(構造体 dirent *pDir);
  35. void スキャンディレクトリと収集(void);
  36. void スリープ(UINT32 iCountMs);
  37.  
  38.  
  39. /****************************************************************
  40. * 機能説明: 主な機能
  41. * 入力パラメータ: なし
  42. * 出力パラメータ: なし
  43. * 戻り値: 0 - 実行完了
  44. * その他の指示: なし
  45. * 変更日 バージョン番号 修正者 変更内容
  46. * -------------------------------------------------------------  
  47. * 20160513 V1.0 作成者: Zhou Zhaoxiong
  48. ************************************************************************/
  49. INT32メイン(void)
  50. {
  51. // サマリーファイルのディレクトリを取得する
  52. snprintf(g_szGatherDir, sizeof(g_szGatherDir)-1, "%s/zhouzx/TestDir/GatherDir" , getenv( "HOME" ));
  53.  
  54. // 要約するファイルのプレフィックスを取得します
  55. snprintf(g_szFilePrefix, sizeof(g_szFilePrefix)-1, "File_" );
  56.  
  57. // 要約するファイルのサフィックスを取得します
  58. snprintf(g_szFileSuffix, sizeof(g_szFileSuffix)-1, ".txt" );
  59.  
  60. // 呼び出し関数実行ファイルの概要
  61. (1)
  62. {
  63. スキャンディレクトリと収集();
  64.  
  65. Sleep(60 * 1000); // 1分ごとにファイルサマリーを実行する
  66. }
  67.  
  68. 0を返します
  69. }
  70.  
  71.  
  72. /******************************************************************************************
  73. * 機能の説明: プレフィックスとサフィックスに基づいてファイルを選択する
  74. * 入力パラメータ: dir-ディレクトリ
  75. * 出力パラメータ: なし
  76. * 戻り値: 0-失敗、1-成功
  77. * その他の指示: なし
  78. * 変更日 バージョン番号 修正者 変更内容
  79. * --------------------------------------------------------------------  
  80. * 20160513 V1.0 作成者: ZhouZhaoxiong
  81. ******************************************************************************/
  82. INT32 SelectFlies(構造体 dirent *pDir)
  83. {
  84. INT32 iPrefixLen = 0;
  85. INT32 iループフラグ = 0;
  86. INT32 iSelectResult = 0;
  87.  
  88. (pDir == NULL )の場合
  89. {
  90. printf( "SelectFlies:入力パラメータがNULLです!\n" );
  91. 0を返します
  92. }
  93.  
  94. // ファイルのプレフィックスとサフィックスを一致させる
  95. iPrefixLen = strlen(g_szFilePrefix); // プレフィックスはg_szFilePrefixです
  96. iSelectResult = ((0 == strncmp(pDir->d_name, g_szFilePrefix, iPrefixLen))
  97. && ((strncmp(&pDir->d_name[strlen(pDir->d_name) - strlen(g_szFileSuffix)], g_szFileSuffix, strlen(g_szFileSuffix)) == 0)));
  98.  
  99. if (iSelectResult == 1) // プレフィックスに一致するファイルが見つかりました
  100. {
  101. 1 を返します
  102. }
  103. それ以外 
  104. {
  105. 0を返します
  106. }
  107. }
  108.  
  109.  
  110. /******************************************************************************************
  111. * 機能の説明: ディレクトリをスキャンし、同じプレフィックスを持つファイルを要約します
  112. * 入力パラメータ: なし
  113. * 出力パラメータ: なし
  114. * 戻り値: なし
  115. * その他の指示: なし
  116. * 変更日 バージョン番号 修正者 変更内容
  117. * --------------------------------------------------------------------  
  118. * 20160513 V1.0 作成者: ZhouZhaoxiong
  119. ******************************************************************************/
  120. void スキャンディレクトリと収集(void)
  121. {
  122. INT32 iScanDirRet = 0;
  123. UINT32 iDirIdx = 0;
  124. UINT32 iFileIdx = 0;
  125. UINT32 iFileCount = 0;
  126. UINT32 iScanedNoFileDirCount = 0;
  127. UINT32 iFileSize = 0;
  128. INT32 iRetVal = 0;
  129. UINT8 szFileDir[256] = {0};
  130. UINT8 szScanedFile[512] = {0};
  131. UINT8 szCmdBuf[256] = {0};
  132. ファイル *fp = NULL ;
  133. 構造体 dirent **ppDirEnt = NULL ;
  134.  
  135. // 各ディレクトリを順番にスキャンしてファイルを要約します
  136. (iDirIdx = 1; iDirIdx <= DIRNUM; iDirIdx ++)の場合
  137. {
  138. memset(szFileDir, 0x00, sizeof(szFileDir));
  139. snprintf(szFileDir, sizeof(szFileDir)-1, "%s/zhouzx/TestDir/FileDir%d" 、getenv( "HOME" 、iDirIdx);
  140.  
  141. iScanDirRet = scandir(szFileDir, &ppDirEnt, SelectFlies, alphasort);
  142. if (iScanDirRet < 0) // ディレクトリのスキャン中にエラーが発生しました
  143. {
  144. printf( "ScanDirAndGather:exec scandir が失敗しました。パス=%s\n" , szFileDir);
  145. 戻る;
  146. }
  147. else if (iScanDirRet == 0) // ディレクトリにファイルがありません
  148. {
  149. printf( "ScanDirAndGather:ディレクトリ%sに条件に合うファイルがありません\n" , szFileDir);
  150.  
  151. スキャンされたファイルディレクトリ数++;
  152. if (iScanedNoFileDirCount >= DIRNUM) // すべてのディレクトリに条件を満たすファイルが存在しないことを示します
  153. {
  154. printf( "ScanDirAndGather: %d 個のディレクトリすべてで条件に合うファイルがスキャンされませんでした\n" , iScanedNoFileDirCount);
  155. 戻る;
  156. }
  157. }
  158. else // 条件を満たすファイルをサマリーディレクトリに移動する
  159. {
  160. (iFileIdx = 0; iFileIdx < iScanDirRet; iFileIdx ++)の場合
  161. {
  162. // まずスキャンしたファイルが空ファイルかどうかを判断し、空ファイルの場合は直接削除し、空ファイルでない場合は移動操作を実行します
  163. memset(szScanedFile, 0x00, sizeof(szScanedFile));
  164. snprintf(szScanedFile, sizeof(szScanedFile) - 1, "%s/%s" , szFileDir, ppDirEnt[iFileIdx]->d_name);
  165. fp = fopen(szScanedFile, "r" );
  166. if (fp == NULL ) // ファイルを開けなかった場合は直接戻ります
  167. {
  168. printf( "ScanDirAndGather:ファイル%sのオープンに失敗しました。確認してください!\n" , szScanedFile);
  169. 戻る;
  170. }
  171. fseek(fp, 0, SEEK_END);
  172. ファイルサイズ = ftell(fp);
  173. if (iFileSize == 0) // ファイルは空のファイルです
  174. {
  175. printf( "ScanDirAndGather:%s は空のファイルなので、直接削除してください!\n" , szScanedFile);
  176. memset(szCmdBuf, 0x00, sizeof(szCmdBuf));
  177. snprintf(szCmdBuf, sizeof(szCmdBuf) - 1, "rm %s" , szScanedFile);
  178. システム(szCmdBuf);
  179. }
  180. それ以外 
  181. {
  182. memset(szCmdBuf, 0x00, sizeof(szCmdBuf));
  183. snprintf(szCmdBuf, sizeof(szCmdBuf) - 1, "mv %s %s" , szScanedFile, g_szGatherDir);
  184. システム(szCmdBuf);
  185.  
  186. printf( "ScanDirAndGather:now, %s\n" , szCmdBuf);
  187.  
  188. ファイルカウント++;
  189. }
  190. }
  191. }
  192. }
  193.  
  194. printf( "ScanDirAndGather: 今回は合計 %d 個のファイルを %s に移動しました\n" , iFileCount, g_szGatherDir);
  195.  
  196. 戻る;
  197. }
  198.  
  199.  
  200. /******************************************************************************************
  201. * 機能説明: プログラム休止状態
  202. * 入力パラメータ: iCountMs - スリープ時間 (単位: ms)
  203. * 出力パラメータ: なし
  204. * 戻り値: なし
  205. * その他の指示: なし
  206. * 変更日 バージョン番号 修正者 変更内容
  207. * ------------------------------------------------------------------  
  208. * 20160513 V1.0 作成者: Zhou Zhaoxiong
  209. ****************************************************************************/
  210. void スリープ(UINT32 iCountMs)
  211. {
  212. 構造体timeval t_timeout = {0};
  213.  
  214. (iCountMs < 1000)の場合
  215. {
  216. t_timeout.tv_sec = 0;
  217. t_timeout.tv_usec = iCountMs * 1000;
  218. }
  219. それ以外 
  220. {
  221. t_timeout.tv_sec = iCountMs / 1000;
  222. t_timeout.tv_usec = (iCountMs % 1000) * 1000;
  223. }
  224. select (0, NULL , NULL , NULL , &t_timeout); // select関数を呼び出してプログラムをブロックする
  225. }

5. プログラムのテスト

記述したプログラム「FileGather.c」を Linux マシンにアップロードし、「gcc -g -o FileGather FileGather.c」コマンドを使用してプログラムをコンパイルし、「FileGather」ファイルを生成します。以下はプログラムの詳細なテストです。

1. プログラムを起動する前に、File_1.txt、File_2.txt、File_3.txt の各ファイルをそれぞれソース ディレクトリ FileDir1、FileDir2、FileDir3 に配置します。プログラムは次のように実行されます。

  1. ScanDirAndGather:今、mv /home/zhou/zhouzx/TestDir/FileDir1/File_1.txt /home/zhou/zhouzx/TestDir/GatherDir  
  2. ScanDirAndGather:今、mv /home/zhou/zhouzx/TestDir/FileDir2/File_2.txt /home/zhou/zhouzx/TestDir/GatherDir  
  3. ScanDirAndGather:今、mv /home/zhou/zhouzx/TestDir/FileDir3/File_3.txt /home/zhou/zhouzx/TestDir/GatherDir  
  4. ScanDirAndGather:今回は合計3つのファイル/home/zhou/zhouzx/TestDir/GatherDir移動しました

ご覧のとおり、ソース ディレクトリ内の 3 つのファイルは存在しなくなりました。これらは結果ディレクトリ GatherDir に移動されました。

  1. ~/zhouzx/TestDir/GatherDir>ll  
  2. -rw——- 1 zhou users 12 2016-05-13 15:14 File_1.txt  
  3. -rw——- 1 zhou users 12 2016-05-13 15:14 File_2.txt
  4. -rw——- 1 周 ユーザー 12 2016-05-13 15:14 File_3.txt

2. しばらくしてから、ファイル File1_4.txt をソース ディレクトリ FileDir1 に配置すると、プログラムは次のように実行されます。

  1. ScanDirAndGather:ディレクトリ /home/zhou/zhouzx/TestDir/FileDir1条件に合うファイルがありませ 
  2. ScanDirAndGather:ディレクトリ /home/zhou/zhouzx/TestDir/FileDir2条件に合うファイルがありませ 
  3. ScanDirAndGather:ディレクトリ /home/zhou/zhouzx/TestDir/FileDir3条件に合うファイルがありませ 
  4. ScanDirAndGather: 条件合うファイルがスキャンされませでした 3ディレクター

ご覧のとおり、プレフィックスが一致しないため、File1_4.txt ファイルはソース ディレクトリ FileDir1 に残っています。

  1. ~/zhouzx/TestDir/FileDir1>ll  
  2. -rw——- 1 周 ユーザー 36 2016-05-13 15:19 File1_4.txt

3. しばらくしてから、File_5.txt ファイルをソース ディレクトリ FileDir2 に置き、File_11.c ファイルをソース ディレクトリ FileDir3 に置きます。プログラムは次のように実行されます。

  1. ScanDirAndGather:ディレクトリ /home/zhou/zhouzx/TestDir/FileDir1条件に合うファイルがありませ 
  2. ScanDirAndGather:今、mv /home/zhou/zhouzx/TestDir/FileDir2/File_5.txt /home/zhou/zhouzx/TestDir/GatherDir  
  3. ScanDirAndGather:ディレクトリ /home/zhou/zhouzx/TestDir/FileDir3条件に合うファイルがありませ 
  4. ScanDirAndGather:今回は合計 1 つのファイル/home/zhou/zhouzx/TestDir/GatherDir移動しました

ソース ディレクトリ FileDir2 内のファイル File_5.txt はサフィックスが一致しないため存在しなくなり、ソース ディレクトリ FileDir3 内のファイル File_11.c はまだ存在していることがわかります。

  1. ~/zhouzx/TestDir/FileDir3>ll  
  2. -rw——- 1 zhou users 4 2016-05-13 15:23 File_11.c

File_5.txt は結果ディレクトリ GatherDir に移動されました:

  1. ~/zhouzx/TestDir/GatherDir>ll  
  2. -rw——- 1 周 ユーザー 12 2016-05-13 15:14 File_1.txt  
  3. -rw——- 1 zhou users 12 2016-05-13 15:14 File_2.txt  
  4. -rw——- 1 周 ユーザー 12 2016-05-13 15:14 File_3.txt  
  5. -rw——- 1 周 ユーザー 36 2016-05-13 15:23 File_5.txt

4. しばらくすると、空のファイル File_7.txt がソース ディレクトリ FileDir2 に配置され、プログラムは次のように実行されます。

  1. ScanDirAndGather:ディレクトリ /home/zhou/zhouzx/TestDir/FileDir1条件に合うファイルがありませ 
  2. ScanDirAndGather:/home/zhou/zhouzx/TestDir/FileDir2/File_7.txt は空のファイルので、直接削除してください  
  3. ScanDirAndGather:ディレクトリ /home/zhou/zhouzx/TestDir/FileDir3条件に合うファイルがありませ 
  4. ScanDirAndGather: 今回、合計 0 個のファイル/home/zhou/zhouzx/TestDir/GatherDir移動しました

ソース ディレクトリ FileDir2 内のファイル File_7.txt が削除されたことがわかります。

  1. ~/zhouzx/TestDir/FileDir2>ll  
  2. 合計 0

6. 需要拡大

この記事の要件と手順に基づいて、要件に対する次の拡張を検討できます。

1. ファイルを移動する前に、結果ディレクトリに同じファイル名のファイルが存在するかどうかを確認します。存在する場合は、ソースディレクトリからファイルを直接削除します。存在しない場合は、ファイルを結果ディレクトリに移動します。

2. 結果ディレクトリ内のファイルが多すぎるのを避けるために、プログラムにクリーンアップ メカニズムを追加して、一定期間以上保存されているファイルを削除することができます。

3. プログラムの柔軟性を反映するために、一部のファイル情報(ファイルのプレフィックス、サフィックス、保存ディレクトリ、スキャン間隔など)を設定ファイルに保存できます。プログラムが起動すると、関連する設定項目の値が読み取られ、後続のディレクトリスキャンとファイル移動操作が実行されます。

[この記事は51CTOコラムニストの周兆雄氏によるオリジナル記事です。著者のWeChat公開アカウント:周の論理(logiczhou)]

この著者の他の記事を読むにはここをクリックしてください

<<:  [文字列処理アルゴリズム] 最長共通部分文字列を取得するためのアルゴリズム設計とCコード実装

>>:  ソースディレクトリ内のファイルをプレフィックスに応じて異なるディレクトリに分散するためのアルゴリズム設計と C コードの実装

ブログ    
ブログ    

推薦する

...

レビュー: 8 月に Github で注目すべき 7 つのデータ サイエンス プロジェクト

[[279134]]機械学習の旅で次の大きな一歩を踏み出す準備はできていますか? 実験的なデータセッ...

人工知能は将来どのように発展するのでしょうか?

20 世紀初頭から、ロボットが人間のように考え始めることができるかどうかについて、人々は疑問を持ち...

年収100万のAI関連職種4つ

ディープラーニング技術の成熟に伴い、AIは最先端技術から徐々に普及しつつあります。最先端のテクノロジ...

強化学習とマルチタスク推奨

1. 短編動画推薦のための2段階制約強化学習アルゴリズム最初に紹介する研究は、Kuaishou が開...

マイクロソフトは下書きを数秒でアプリに変換し、Mac Miniのようなミニデスクトップコンピューターを発売

この記事はAI新メディアQuantum Bit(公開アカウントID:QbitAI)より許可を得て転載...

GPT-4とMidjourneyに加えて、Tan Pingの起業家チームは3D基本モデルを構築したいと考えています。

少し前にOpenAIが驚くべき生成効果を持つグラフィックモデルDALL・E 3をリリースしました。た...

マスクとイリヤのプライベートメールがクロードによって解読され、OpenAIの暗号化された情報が公開され、Googleが損害を被った

OpenAIとマスク氏は激しく議論していたが、誤ってClaude 3の新しいスキルを公開してしまった...

...

モデル融合、ハイブリッド専門家、小規模LLM、2024年のLLMの発展方向を理解するためのいくつかの論文

過去2023年間で、大規模言語モデル(LLM)は潜在力と複雑さの両面で急速に成長しました。 2024...

OpenAI、開発者向けGPTチャットボットAPIのメジャーアップデートを発表、価格を値下げ

OpenAI は本日、大規模言語モデル API (GPT-4 および gpt-3.5-turbo を...

...

...

...

中国情報通信研究院が2021年最初の「信頼できるAI成果」を発表、百度が5つの賞を受賞

[[416150]]グローバルな AI ガバナンスのコンセンサスを実装し、信頼できる AI テクノロ...